├── Sparkle.framework ├── Versions │ ├── Current │ └── A │ │ ├── Sparkle │ │ ├── Resources │ │ ├── fr_CA.lproj │ │ ├── fr.lproj │ │ │ ├── fr.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── relaunch │ │ ├── de.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── en.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── es.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── it.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── nl.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── ru.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── sv.lproj │ │ │ ├── Sparkle.strings │ │ │ ├── SUUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ ├── SUAutomaticUpdateAlert.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ │ └── SUUpdatePermissionPrompt.nib │ │ │ │ ├── keyedobjects.nib │ │ │ │ ├── info.nib │ │ │ │ └── classes.nib │ │ ├── SUStatus.nib │ │ │ ├── keyedobjects.nib │ │ │ ├── info.nib │ │ │ └── classes.nib │ │ ├── Info.plist │ │ ├── License.txt │ │ └── SUModelTranslation.plist │ │ └── Headers │ │ ├── Sparkle.h │ │ ├── SUAppcast.h │ │ ├── SUVersionComparisonProtocol.h │ │ ├── SUAppcastItem.h │ │ └── SUUpdater.h ├── Headers ├── Resources └── Sparkle ├── RubyChinaReader ├── NSDate+TimeAgo.h ├── Resources │ ├── icon.icns │ └── Credits.html ├── en.lproj │ └── InfoPlist.strings ├── RubyChinaReader-Prefix.pch ├── RCRTopic.m ├── Changes.html ├── RCRNode.m ├── main.m ├── RCRTableRowView.h ├── RCRUrlBuilder.h ├── RCROptionsViewController.h ├── RCRAccountViewController.h ├── RCRNode.h ├── RCRPrefsController.h ├── RCRAppController.h ├── RCRTopicDetailController.h ├── RCRUserDetailViewController.h ├── RCRUrlBuilder.m ├── RCRAppDelegate.h ├── RCRInfoViewController.h ├── RCRSettingsManager.h ├── RCRTopicsViewController.h ├── RCRTopicCellView.h ├── RCRTopicCellView.m ├── RCRUserDetailViewController.m ├── RCRTopic.h ├── RCRUser.h ├── RCROptionsViewController.m ├── SynthesizeSingleton.h ├── RCRTopicDetailController.m ├── RCRAccountViewController.m ├── RubyChinaReader-Info.plist ├── RCRInfoViewController.m ├── NSDate+TimeAgo.m ├── RCRUser.m ├── RCRPrefsController.m ├── RCRSettingsManager.m ├── RCRAppDelegate.m ├── RCRTableRowView.m ├── Preferences.xib ├── RCRAppController.m ├── RCRTopicsViewController.m ├── RCRTopicDetailController.xib └── RCRUserDetailViewController.xib ├── RubyChinaReaderTests ├── en.lproj │ └── InfoPlist.strings ├── RubyChinaReaderTests.h ├── RubyChinaReaderTests.m └── RubyChinaReaderTests-Info.plist ├── .gitignore ├── CHANGELOG ├── Changes.html ├── README.md ├── Rakefile └── update.xml /Sparkle.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /Sparkle.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /Sparkle.framework/Resources: -------------------------------------------------------------------------------- 1 | Versions/Current/Resources -------------------------------------------------------------------------------- /Sparkle.framework/Sparkle: -------------------------------------------------------------------------------- 1 | Versions/Current/Sparkle -------------------------------------------------------------------------------- /RubyChinaReader/NSDate+TimeAgo.h: -------------------------------------------------------------------------------- 1 | @interface NSDate (TimeAgo) 2 | -(NSString *)timeAgo; 3 | @end 4 | -------------------------------------------------------------------------------- /RubyChinaReaderTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build/ 3 | */xcuserdata 4 | xcuserdata/ 5 | *.xcworkspace/ 6 | SharedLib 7 | *.mode1v3 8 | *.pbxuser 9 | -------------------------------------------------------------------------------- /RubyChinaReader/Resources/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/RubyChinaReader/Resources/icon.icns -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Sparkle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Sparkle -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/fr_CA.lproj: -------------------------------------------------------------------------------- 1 | /Users/andym/Development/Build Products/Release/Sparkle.framework/Resources/fr.lproj -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/fr.lproj/fr.lproj: -------------------------------------------------------------------------------- 1 | /Users/andym/Development/Build Products/Release/Sparkle.framework/Resources/fr.lproj -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | == 0.1 2 | 3 | 2012-04-03 4 | 5 | * 增加对加载用户上传头像的支持(之前只支持显示gravatar头像)。 6 | 7 | == 0.1b 8 | 9 | 2012-03-14 10 | 11 | 原始预览版。 12 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/relaunch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/relaunch -------------------------------------------------------------------------------- /RubyChinaReader/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | CFBundleName = "Ruby China"; 4 | CFBundleDisplayName = "Ruby China"; 5 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/de.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/es.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/fr.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/it.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/nl.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/ru.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/sv.lproj/Sparkle.strings -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/SUStatus.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/SUStatus.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ashchan/ruby-china-reader/HEAD/Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib -------------------------------------------------------------------------------- /RubyChinaReader/RubyChinaReader-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'RubyChinaReader' target in the 'RubyChinaReader' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import "SynthesizeSingleton.h" 8 | #endif 9 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRTopic.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRTopic.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/4/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRTopic.h" 10 | 11 | @implementation RCRTopic 12 | 13 | @end -------------------------------------------------------------------------------- /RubyChinaReader/Changes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 |

Ruby China Reader Changes

11 | 12 |

0.1b

13 |

2012-03-06

14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRNode.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/13/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRNode.h" 10 | 11 | @implementation RCRNode 12 | 13 | @synthesize nodeId, name; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RubyChinaReader/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 2/28/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /RubyChinaReaderTests/RubyChinaReaderTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // RubyChinaReaderTests.h 3 | // RubyChinaReaderTests 4 | // 5 | // Created by James Chen on 2/28/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RubyChinaReaderTests : SenTestCase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRTableRowView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRTableRowView.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/4/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCRTableRowView : NSTableRowView 12 | 13 | @property (retain) id objectValue; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRUrlBuilder.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRUrlBuilder.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/7/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCRUrlBuilder : NSObject 12 | 13 | + (NSURL *)urlWithPath:(NSString *)path; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Changes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Ruby China Reader Changes 7 | 10 | 11 | 12 |

Ruby China Reader Changes

13 | 14 |

0.1b

15 |

2012-03-14

16 |

原始预览版。

17 | 18 | 19 | -------------------------------------------------------------------------------- /RubyChinaReader/RCROptionsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCROptionsViewController.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/3/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCROptionsViewController : NSViewController 12 | 13 | - (NSImage *)image; 14 | @end 15 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRAccountViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRAccountViewController.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/3/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCRAccountViewController : NSViewController 12 | 13 | - (NSImage *)image; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRNode.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/13/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCRNode : NSObject 12 | 13 | @property (strong) NSNumber *nodeId; 14 | @property (strong) NSString *name; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRPrefsController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRPrefsController.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/12/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "DBPrefsWindowController.h" 10 | 11 | @interface RCRPrefsController : DBPrefsWindowController 12 | 13 | - (void)showPreferences; 14 | - (void)showAbout; 15 | - (void)showAccount; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRAppController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRAppController.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 2/28/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "EDSideBar.h" 10 | 11 | @interface RCRAppController : NSWindowController 12 | 13 | - (void)showMainWindow; 14 | 15 | + (RCRAppController *)sharedAppController; 16 | 17 | - (void)newTopic; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRTopicDetailController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRTopicDetailController.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/7/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class RCRTopic; 12 | 13 | @interface RCRTopicDetailController : NSWindowController 14 | 15 | @property (assign) IBOutlet NSTextView *topicView; 16 | 17 | - (id)initWithTopic:(RCRTopic *)topic; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRUserDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRUserDetailViewController.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/7/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCRUserDetailViewController : NSViewController 12 | @property (weak) IBOutlet NSTextField *name; 13 | @property (weak) IBOutlet NSTextField *tagline; 14 | @property (weak) IBOutlet NSTextField *location; 15 | @end 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A simple reader for [Ruby China Group](http://ruby-china.org) 2 | 3 | booting... 4 | 5 | ## How to build 6 | 7 | * under the project root directory, run `rake` to install 3rd-party dependencies 8 | * use Xcode 4.3 or above to build the project 9 | 10 | ## Requirements 11 | 12 | * Mac OS X 10.7+ 13 | 14 | ## License 15 | 16 | Copyright (c) 2012 James Chen 17 | 18 | Released under the MIT license: 19 | 20 | * [www.opensource.org/licenses/MIT](http://www.opensource.org/licenses/MIT) 21 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRUrlBuilder.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRUrlBuilder.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/7/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRUrlBuilder.h" 10 | 11 | @implementation RCRUrlBuilder 12 | 13 | NSString *const RubyChinaUrl = @"http://ruby-china.org"; 14 | 15 | + (NSURL *)urlWithPath:(NSString *)path { 16 | return [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", RubyChinaUrl, path]]; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /RubyChinaReader/Resources/Credits.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 |

Brought to you by James Chen

11 |

Follow @ashchan on twitter.

12 |

源代码: github.com/ashchan/ruby-china-reader

13 | 14 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRAppDelegate.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 2/28/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCRAppDelegate : NSObject 12 | 13 | - (IBAction)aboutClicked:(id)sender; 14 | - (IBAction)preferencesClicked:(id)sender; 15 | - (IBAction)showMainWindow:(id)sender; 16 | - (IBAction)closeWindow:(id)sender; 17 | - (IBAction)newTopicClicked:(id)sender; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBOldestOS 8 | 5 9 | IBOpenObjects 10 | 11 | IBSystem Version 12 | 9E17 13 | targetFramework 14 | IBCocoaFramework 15 | 16 | 17 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBOldestOS 8 | 5 9 | IBOpenObjects 10 | 11 | IBSystem Version 12 | 9E17 13 | targetFramework 14 | IBCocoaFramework 15 | 16 | 17 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRInfoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRInfoViewController.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/3/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCRInfoViewController : NSViewController 12 | 13 | @property (weak) IBOutlet NSTextField *appName; 14 | @property (weak) IBOutlet NSTextField *appVersion; 15 | @property (assign) IBOutlet NSTextView *credits; 16 | @property (weak) IBOutlet NSTextField *copyrightInfo; 17 | 18 | - (NSImage *)image; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBOldestOS 8 | 5 9 | IBOpenObjects 10 | 11 | IBSystem Version 12 | 9D34 13 | targetFramework 14 | IBCocoaFramework 15 | 16 | 17 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBOldestOS 8 | 5 9 | IBOpenObjects 10 | 11 | IBSystem Version 12 | 9E17 13 | targetFramework 14 | IBCocoaFramework 15 | 16 | 17 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBOldestOS 8 | 5 9 | IBOpenObjects 10 | 11 | IBSystem Version 12 | 9E17 13 | targetFramework 14 | IBCocoaFramework 15 | 16 | 17 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRSettingsManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRSettingsManager.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/13/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCRSettingsManager : NSObject 12 | 13 | + (RCRSettingsManager *)sharedRCRSettingsManager; 14 | 15 | @property (weak) NSString *privateToken; 16 | @property BOOL startAtLogin; 17 | @property NSInteger refreshInterval; 18 | @property (readonly) NSInteger minRefreshInterval; 19 | @property NSTimeInterval lastTimeRefreshed; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRTopicsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRTopicsViewController.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/3/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSDate+TimeAgo.h" 11 | 12 | @interface RCRTopicsViewController : NSViewController 13 | 14 | - (void)start; 15 | - (void)refresh; 16 | - (IBAction)newTopic:(id)sender; 17 | - (IBAction)userImageClicked:(id)sender; 18 | 19 | @property BOOL canRefresh; 20 | @property BOOL canPostTopic; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBOldestOS 8 | 5 9 | IBOpenObjects 10 | 11 | 6 12 | 13 | IBSystem Version 14 | 9D34 15 | targetFramework 16 | IBCocoaFramework 17 | 18 | 19 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRTopicCellView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRTopicCellView.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/4/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCRTopicCellView : NSTableCellView 12 | 13 | @property (weak) IBOutlet NSTextField *topicTitle; 14 | @property (weak) IBOutlet NSButton *repliesCount; 15 | @property (weak) IBOutlet NSTextField *nodeName; 16 | @property (weak) IBOutlet NSTextField *repliedAt; 17 | @property (weak) IBOutlet NSButton *gravatarButton; 18 | @property (weak) IBOutlet NSProgressIndicator *progressIndicator; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /RubyChinaReaderTests/RubyChinaReaderTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // RubyChinaReaderTests.m 3 | // RubyChinaReaderTests 4 | // 5 | // Created by James Chen on 2/28/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RubyChinaReaderTests.h" 10 | 11 | @implementation RubyChinaReaderTests 12 | 13 | - (void)setUp 14 | { 15 | [super setUp]; 16 | 17 | // Set-up code here. 18 | } 19 | 20 | - (void)tearDown 21 | { 22 | // Tear-down code here. 23 | 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample 28 | { 29 | STFail(@"Unit tests are not implemented yet in RubyChinaReaderTests"); 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Headers/Sparkle.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sparkle.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 3/16/06. (Modified by CDHW on 23/12/07) 6 | // Copyright 2006 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SPARKLE_H 10 | #define SPARKLE_H 11 | 12 | // This list should include the shared headers. It doesn't matter if some of them aren't shared (unless 13 | // there are name-space collisions) so we can list all of them to start with: 14 | 15 | #import 16 | 17 | #import 18 | #import 19 | #import 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | IBSystem Version 14 | 9E17 15 | targetFramework 16 | IBCocoaFramework 17 | 18 | 19 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | 3 | task :default => [:install] 4 | 5 | desc "install 3rd-party libs" 6 | task :install do 7 | shared_lib = "SharedLib" 8 | FileUtils.mkdir_p(shared_lib) 9 | 10 | FileUtils.cd("#{shared_lib}"); 11 | 12 | [ 13 | ["https://github.com/kgn/DBPrefsWindowController.git", "master"], 14 | ["https://github.com/RestKit/RestKit.git", "development"], 15 | ["https://github.com/erndev/EDSidebar.git", "master"], 16 | ["https://github.com/irons/EMKeychain.git", "master"], 17 | ["https://github.com/enormego/EGOCache.git", "master"], 18 | ].each do |lib| 19 | `git clone #{lib[0]} -b #{lib[1]} --recursive` 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/SUStatus.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 10A96 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9E17 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBDocumentLocation 6 | 69 14 356 240 0 0 1280 778 7 | IBFramework Version 8 | 489.0 9 | IBLastKnownRelativeProjectPath 10 | ../Sparkle.xcodeproj 11 | IBOldestOS 12 | 5 13 | IBSystem Version 14 | 9D34 15 | targetFramework 16 | IBCocoaFramework 17 | 18 | 19 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 18 14 | 15 | IBSystem Version 16 | 10A96 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 658 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9C7010 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 5 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9E17 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 10A96 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 667 7 | IBLastKnownRelativeProjectPath 8 | ../../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 9D34 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 15 | IBSystem Version 16 | 10A96 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 670 7 | IBLastKnownRelativeProjectPath 8 | ../Sparkle.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 6 14 | 41 15 | 16 | IBSystem Version 17 | 10A96 18 | targetFramework 19 | IBCocoaFramework 20 | 21 | 22 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRTopicCellView.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRTopicCellView.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/4/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRTopicCellView.h" 10 | 11 | @implementation RCRTopicCellView 12 | 13 | @synthesize topicTitle, nodeName, gravatarButton, repliesCount, repliedAt, progressIndicator; 14 | 15 | - (id)initWithFrame:(NSRect)frame 16 | { 17 | self = [super initWithFrame:frame]; 18 | if (self) { 19 | } 20 | 21 | return self; 22 | } 23 | 24 | - (void)drawRect:(NSRect)dirtyRect 25 | { 26 | // Drawing code here. 27 | } 28 | 29 | - (void)viewWillDraw { 30 | [super viewWillDraw]; 31 | [self.nodeName sizeToFit]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRUserDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRUserDetailViewController.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/7/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRUserDetailViewController.h" 10 | 11 | @interface RCRUserDetailViewController () 12 | 13 | @end 14 | 15 | @implementation RCRUserDetailViewController 16 | 17 | @synthesize name, tagline, location; 18 | 19 | - (NSString *)nibName { 20 | return @"RCRUserDetailViewController"; 21 | } 22 | 23 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 24 | { 25 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 26 | if (self) { 27 | // Initialization code here. 28 | } 29 | 30 | return self; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /RubyChinaReaderTests/RubyChinaReaderTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.ashchan.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRTopic.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRTopic.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/4/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RCRUser.h" 11 | 12 | @interface RCRTopic : NSObject 13 | 14 | @property (strong) NSNumber *topicId; 15 | @property (strong) NSString *title; 16 | //@property (strong) NSString *body; 17 | //@property (strong) NSString *bodyHtml; 18 | @property (strong) NSNumber *repliesCount; 19 | @property (strong) NSDate *createdDate; 20 | @property (strong) NSDate *updatedDate; 21 | @property (strong) NSDate *repliedAt; 22 | @property (strong) NSString *nodeName; 23 | @property (strong) NSNumber *nodeId; 24 | @property (strong) RCRUser *user; 25 | @property (strong) NSString *lastReplyUserLogin; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Headers/SUAppcast.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUAppcast.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 3/12/06. 6 | // Copyright 2006 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUAPPCAST_H 10 | #define SUAPPCAST_H 11 | 12 | @class SUAppcastItem; 13 | @interface SUAppcast : NSObject { 14 | NSArray *items; 15 | NSString *userAgentString; 16 | id delegate; 17 | NSMutableData *incrementalData; 18 | } 19 | 20 | - (void)fetchAppcastFromURL:(NSURL *)url; 21 | - (void)setDelegate:delegate; 22 | - (void)setUserAgentString:(NSString *)userAgentString; 23 | 24 | - (NSArray *)items; 25 | 26 | @end 27 | 28 | @interface NSObject (SUAppcastDelegate) 29 | - (void)appcastDidFinishLoading:(SUAppcast *)appcast; 30 | - (void)appcast:(SUAppcast *)appcast failedToLoadWithError:(NSError *)error; 31 | @end 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRUser.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCRUser.h 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/4/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString *const RCRTopicPropertyNamedGravatar; 12 | 13 | @interface RCRUser : NSObject 14 | 15 | @property (strong) NSString *login; 16 | @property (strong) NSString *name; 17 | @property (strong) NSString *location; 18 | @property (strong) NSString *bio; 19 | @property (strong) NSString *tagline; 20 | @property (strong) NSString *website; 21 | @property (strong) NSString *githubUrl; 22 | @property (strong) NSString *gravatarHash; 23 | @property (strong) NSString *avatarUrl; 24 | 25 | @property (assign) BOOL loadingGravatar; 26 | @property (strong) NSImage *gravatar; 27 | 28 | - (void)loadGravatar; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | Sparkle 9 | CFBundleIdentifier 10 | org.andymatuschak.Sparkle 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | Sparkle 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.5 Beta 6 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 313 23 | 24 | 25 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUVersionComparisonProtocol.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 12/21/07. 6 | // Copyright 2007 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUVERSIONCOMPARISONPROTOCOL_H 10 | #define SUVERSIONCOMPARISONPROTOCOL_H 11 | 12 | /*! 13 | @protocol 14 | @abstract Implement this protocol to provide version comparison facilities for Sparkle. 15 | */ 16 | @protocol SUVersionComparison 17 | 18 | /*! 19 | @method 20 | @abstract An abstract method to compare two version strings. 21 | @discussion Should return NSOrderedAscending if b > a, NSOrderedDescending if b < a, and NSOrderedSame if they are equivalent. 22 | */ 23 | - (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; 24 | 25 | @end 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2006 Andy Matuschak 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. -------------------------------------------------------------------------------- /RubyChinaReader/RCROptionsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCROptionsViewController.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/3/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCROptionsViewController.h" 10 | #import "RCRSettingsManager.h" 11 | 12 | @interface RCROptionsViewController () 13 | @property NSInteger refreshInterval; 14 | @end 15 | 16 | @implementation RCROptionsViewController 17 | 18 | - (NSString *)nibName { 19 | return @"RCROptionsViewController"; 20 | } 21 | 22 | - (NSImage *)image { 23 | return [NSImage imageNamed:NSImageNamePreferencesGeneral]; 24 | } 25 | 26 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 27 | { 28 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 29 | if (self) { 30 | self.title = @"General"; 31 | } 32 | 33 | return self; 34 | } 35 | 36 | - (void)setRefreshInterval:(NSInteger)interval { 37 | [RCRSettingsManager sharedRCRSettingsManager].refreshInterval = interval; 38 | } 39 | 40 | - (NSInteger)refreshInterval { 41 | return [RCRSettingsManager sharedRCRSettingsManager].refreshInterval; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | { 2 | IBClasses = ( 3 | { 4 | CLASS = FirstResponder; 5 | LANGUAGE = ObjC; 6 | SUPERCLASS = NSObject; 7 | }, 8 | { 9 | CLASS = NSApplication; 10 | LANGUAGE = ObjC; 11 | SUPERCLASS = NSResponder; 12 | }, 13 | { 14 | CLASS = NSObject; 15 | LANGUAGE = ObjC; 16 | }, 17 | { 18 | ACTIONS = { 19 | installUpdate = id; 20 | remindMeLater = id; 21 | skipThisVersion = id; 22 | }; 23 | CLASS = SUUpdateAlert; 24 | LANGUAGE = ObjC; 25 | OUTLETS = { 26 | delegate = id; 27 | description = NSTextField; 28 | releaseNotesView = WebView; 29 | }; 30 | SUPERCLASS = SUWindowController; 31 | }, 32 | { 33 | CLASS = SUWindowController; 34 | LANGUAGE = ObjC; 35 | SUPERCLASS = NSWindowController; 36 | } 37 | ); 38 | IBVersion = 1; 39 | } -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Headers/SUAppcastItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUAppcastItem.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 3/12/06. 6 | // Copyright 2006 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUAPPCASTITEM_H 10 | #define SUAPPCASTITEM_H 11 | 12 | @interface SUAppcastItem : NSObject { 13 | NSString *title; 14 | NSDate *date; 15 | NSString *itemDescription; 16 | 17 | NSURL *releaseNotesURL; 18 | 19 | NSString *DSASignature; 20 | NSString *minimumSystemVersion; 21 | 22 | NSURL *fileURL; 23 | NSString *versionString; 24 | NSString *displayVersionString; 25 | 26 | NSDictionary *propertiesDictionary; 27 | } 28 | 29 | // Initializes with data from a dictionary provided by the RSS class. 30 | - initWithDictionary:(NSDictionary *)dict; 31 | 32 | - (NSString *)title; 33 | - (NSString *)versionString; 34 | - (NSString *)displayVersionString; 35 | - (NSDate *)date; 36 | - (NSString *)itemDescription; 37 | - (NSURL *)releaseNotesURL; 38 | - (NSURL *)fileURL; 39 | - (NSString *)DSASignature; 40 | - (NSString *)minimumSystemVersion; 41 | 42 | // Returns the dictionary provided in initWithDictionary; this might be useful later for extensions. 43 | - (NSDictionary *)propertiesDictionary; 44 | 45 | @end 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /update.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ruby China Reader Update 5 | https://raw.github.com/ashchan/ruby-china-reader/master/update.xml 6 | Ruby China Reader Update Feed 7 | en 8 | 9 | Version 0.1 10 | 10.7.0 11 | Tue, 3 Apr 00:15:00 +0900 12 | 17 | 0.1 19 |

2012-04-03

20 |
    21 |
  • * 增加对加载用户上传头像的支持(之前只支持显示gravatar头像)。
  • 22 |
23 | 24 |

0.1b

25 |

2012-03-14

26 |

原始预览版。

27 | ]]>
28 |
29 |
30 |
31 | -------------------------------------------------------------------------------- /RubyChinaReader/SynthesizeSingleton.h: -------------------------------------------------------------------------------- 1 | // 2 | // SynthesizeSingleton.h 3 | // CocoaWithLove 4 | // 5 | // Created by Matt Gallagher on 20/10/08. 6 | // Copyright 2008 Matt Gallagher. All rights reserved. 7 | // 8 | // Permission is given to use this source code file, free of charge, in any 9 | // project, commercial or otherwise, entirely at your risk, with the condition 10 | // that any redistribution (in part or whole) of source code must retain 11 | // this copyright and permission notice. Attribution in compiled projects is 12 | // appreciated but not required. 13 | // 14 | 15 | #define SYNTHESIZE_SINGLETON_FOR_CLASS(classname) \ 16 | \ 17 | static classname *shared##classname = nil; \ 18 | \ 19 | + (classname *)shared##classname \ 20 | { \ 21 | @synchronized(self) \ 22 | { \ 23 | if (shared##classname == nil) \ 24 | { \ 25 | shared##classname = [[self alloc] init]; \ 26 | } \ 27 | } \ 28 | \ 29 | return shared##classname; \ 30 | } \ 31 | \ 32 | + (id)allocWithZone:(NSZone *)zone \ 33 | { \ 34 | @synchronized(self) \ 35 | { \ 36 | if (shared##classname == nil) \ 37 | { \ 38 | shared##classname = [super allocWithZone:zone]; \ 39 | return shared##classname; \ 40 | } \ 41 | } \ 42 | \ 43 | return nil; \ 44 | } \ 45 | \ 46 | - (id)copyWithZone:(NSZone *)zone \ 47 | { \ 48 | return self; \ 49 | } \ 50 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRTopicDetailController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRTopicDetailController.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/7/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRTopicDetailController.h" 10 | #import "RCRTopic.h" 11 | 12 | @interface RCRTopicDetailController () { 13 | RCRTopic *_topic; 14 | } 15 | @end 16 | 17 | @implementation RCRTopicDetailController 18 | 19 | @synthesize topicView; 20 | 21 | - (id)initWithTopic:(RCRTopic *)topic { 22 | if (self = [super initWithWindowNibName:@"RCRTopicDetailController"]) { 23 | _topic = topic; 24 | } 25 | return self; 26 | } 27 | 28 | - (void)windowDidLoad 29 | { 30 | [super windowDidLoad]; 31 | 32 | NSString *htmlBody = @""; 33 | //htmlBody = [htmlBody stringByAppendingString:_topic.bodyHtml]; 34 | //htmlBody = [htmlBody stringByAppendingString:@""]; 35 | 36 | NSData *htmlData = [htmlBody dataUsingEncoding:NSUTF8StringEncoding]; 37 | NSAttributedString *html = [[NSAttributedString alloc] initWithHTML:htmlData 38 | options:nil 39 | documentAttributes:nil]; 40 | [topicView insertText:html]; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/de.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/es.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/fr.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/it.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/nl.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/ru.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/sv.lproj/SUAutomaticUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | doNotInstall 19 | id 20 | installLater 21 | id 22 | installNow 23 | id 24 | 25 | CLASS 26 | SUAutomaticUpdateAlert 27 | LANGUAGE 28 | ObjC 29 | SUPERCLASS 30 | SUWindowController 31 | 32 | 33 | CLASS 34 | FirstResponder 35 | LANGUAGE 36 | ObjC 37 | SUPERCLASS 38 | NSObject 39 | 40 | 41 | CLASS 42 | NSObject 43 | LANGUAGE 44 | ObjC 45 | 46 | 47 | IBVersion 48 | 1 49 | 50 | 51 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRAccountViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRAccountViewController.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/3/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRAccountViewController.h" 10 | #import "RCRUrlBuilder.h" 11 | #import "RCRSettingsManager.h" 12 | 13 | @interface RCRAccountViewController () 14 | - (IBAction)privateTokenButtonClicked:(id)sender; 15 | @property (weak) NSString *privateTokey; 16 | @end 17 | 18 | @implementation RCRAccountViewController 19 | 20 | @dynamic privateTokey; 21 | 22 | - (NSString *)nibName { 23 | return @"RCRAccountViewController"; 24 | } 25 | 26 | - (NSImage *)image { 27 | return [NSImage imageNamed:NSImageNameUser]; 28 | } 29 | 30 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 31 | { 32 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 33 | if (self) { 34 | self.title = @"Account"; 35 | } 36 | 37 | return self; 38 | } 39 | 40 | - (NSString *)privateTokey { 41 | return [RCRSettingsManager sharedRCRSettingsManager].privateToken; 42 | } 43 | 44 | - (void)setPrivateTokey:(NSString *)token { 45 | [RCRSettingsManager sharedRCRSettingsManager].privateToken = token; 46 | } 47 | 48 | - (IBAction)privateTokenButtonClicked:(id)sender { 49 | [[NSWorkspace sharedWorkspace] openURL:[RCRUrlBuilder urlWithPath:@"/account/edit"]]; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /RubyChinaReader/RubyChinaReader-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | icon 11 | CFBundleIdentifier 12 | com.ashchan.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 0.1 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 20 25 | LSApplicationCategoryType 26 | public.app-category.social-networking 27 | LSHasLocalizedDisplayName 28 | 29 | LSMinimumSystemVersion 30 | ${MACOSX_DEPLOYMENT_TARGET} 31 | NSHumanReadableCopyright 32 | Copyright © 2012 James Chen. All rights reserved. 33 | NSMainNibFile 34 | MainMenu 35 | NSPrincipalClass 36 | NSApplication 37 | SUFeedURL 38 | https://raw.github.com/ashchan/ruby-china-reader/master/update.xml 39 | 40 | 41 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/SUStatus.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | CLASS 25 | FirstResponder 26 | LANGUAGE 27 | ObjC 28 | SUPERCLASS 29 | NSObject 30 | 31 | 32 | CLASS 33 | NSObject 34 | LANGUAGE 35 | ObjC 36 | 37 | 38 | CLASS 39 | SUStatusController 40 | LANGUAGE 41 | ObjC 42 | OUTLETS 43 | 44 | actionButton 45 | NSButton 46 | progressBar 47 | NSProgressIndicator 48 | 49 | SUPERCLASS 50 | SUWindowController 51 | 52 | 53 | IBVersion 54 | 1 55 | 56 | 57 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | NSObject 10 | LANGUAGE 11 | ObjC 12 | 13 | 14 | CLASS 15 | SUWindowController 16 | LANGUAGE 17 | ObjC 18 | SUPERCLASS 19 | NSWindowController 20 | 21 | 22 | ACTIONS 23 | 24 | finishPrompt 25 | id 26 | toggleMoreInfo 27 | id 28 | 29 | CLASS 30 | SUUpdatePermissionPrompt 31 | LANGUAGE 32 | ObjC 33 | OUTLETS 34 | 35 | delegate 36 | id 37 | descriptionTextField 38 | NSTextField 39 | moreInfoButton 40 | NSButton 41 | moreInfoView 42 | NSView 43 | 44 | SUPERCLASS 45 | SUWindowController 46 | 47 | 48 | CLASS 49 | FirstResponder 50 | LANGUAGE 51 | ObjC 52 | SUPERCLASS 53 | NSObject 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/sv.lproj/SUUpdatePermissionPrompt.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | ACTIONS 17 | 18 | finishPrompt 19 | id 20 | toggleMoreInfo 21 | id 22 | 23 | CLASS 24 | SUUpdatePermissionPrompt 25 | LANGUAGE 26 | ObjC 27 | OUTLETS 28 | 29 | delegate 30 | id 31 | descriptionTextField 32 | NSTextField 33 | moreInfoButton 34 | NSButton 35 | moreInfoView 36 | NSView 37 | 38 | SUPERCLASS 39 | SUWindowController 40 | 41 | 42 | CLASS 43 | FirstResponder 44 | LANGUAGE 45 | ObjC 46 | SUPERCLASS 47 | NSObject 48 | 49 | 50 | CLASS 51 | NSObject 52 | LANGUAGE 53 | ObjC 54 | 55 | 56 | IBVersion 57 | 1 58 | 59 | 60 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRInfoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRInfoViewController.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/3/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRInfoViewController.h" 10 | 11 | @interface RCRInfoViewController () 12 | 13 | @end 14 | 15 | @implementation RCRInfoViewController 16 | 17 | @synthesize appName, appVersion, credits, copyrightInfo; 18 | 19 | - (NSString *)nibName { 20 | return @"RCRInfoViewController"; 21 | } 22 | 23 | - (NSImage *)image { 24 | return [NSImage imageNamed:NSImageNameInfo]; 25 | } 26 | 27 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 28 | { 29 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 30 | if (self) { 31 | self.title = @"About"; 32 | } 33 | 34 | return self; 35 | } 36 | 37 | - (void)awakeFromNib { 38 | NSBundle *bundle = [NSBundle mainBundle]; 39 | appName.stringValue = [bundle objectForInfoDictionaryKey:@"CFBundleDisplayName"]; 40 | appVersion.stringValue = [NSString stringWithFormat:@"Version %@ (%@)", 41 | [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"], 42 | [bundle objectForInfoDictionaryKey:@"CFBundleVersion"]]; 43 | copyrightInfo.stringValue = [bundle objectForInfoDictionaryKey:@"NSHumanReadableCopyright"]; 44 | 45 | NSAttributedString *creditsHtml = [[NSAttributedString alloc] initWithPath:[bundle pathForResource:@"Credits" ofType:@"html"] 46 | documentAttributes:nil]; 47 | [credits insertText:creditsHtml]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /RubyChinaReader/NSDate+TimeAgo.m: -------------------------------------------------------------------------------- 1 | #import "NSDate+TimeAgo.h" 2 | 3 | @implementation NSDate (TimeAgo) 4 | 5 | 6 | -(NSString *)timeAgo { 7 | NSDate *now = [NSDate date]; 8 | double deltaSeconds = fabs([self timeIntervalSinceDate:now]); 9 | double deltaMinutes = deltaSeconds / 60.0f; 10 | 11 | if(deltaSeconds < 5) { 12 | return @"刚刚"; 13 | } else if(deltaSeconds < 60) { 14 | return [NSString stringWithFormat:@"%d秒前", (int)deltaSeconds]; 15 | } else if(deltaSeconds < 120) { 16 | return @"1分钟前"; 17 | } else if (deltaMinutes < 60) { 18 | return [NSString stringWithFormat:@"%d分钟前", (int)deltaMinutes]; 19 | } else if (deltaMinutes < 120) { 20 | return @"1小时前"; 21 | } else if (deltaMinutes < (24 * 60)) { 22 | return [NSString stringWithFormat:@"%d小时前", (int)floor(deltaMinutes/60)]; 23 | } else if (deltaMinutes < (24 * 60 * 2)) { 24 | return @"昨天"; 25 | } else if (deltaMinutes < (24 * 60 * 7)) { 26 | return [NSString stringWithFormat:@"%d天前", (int)floor(deltaMinutes/(60 * 24))]; 27 | } else if (deltaMinutes < (24 * 60 * 14)) { 28 | return @"上周"; 29 | } else if (deltaMinutes < (24 * 60 * 31)) { 30 | return [NSString stringWithFormat:@"%d周前", (int)floor(deltaMinutes/(60 * 24 * 7))]; 31 | } else if (deltaMinutes < (24 * 60 * 61)) { 32 | return @"上个月"; 33 | } else if (deltaMinutes < (24 * 60 * 365.25)) { 34 | return [NSString stringWithFormat:@"%d月前", (int)floor(deltaMinutes/(60 * 24 * 30))]; 35 | } else if (deltaMinutes < (24 * 60 * 731)) { 36 | return @"去年"; 37 | } 38 | return [NSString stringWithFormat:@"%d年前", (int)floor(deltaMinutes/(60 * 24 * 365))]; 39 | } 40 | 41 | @end -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/de.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/es.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/fr.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/it.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/nl.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/ru.lproj/SUUpdateAlert.nib/classes.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBClasses 6 | 7 | 8 | CLASS 9 | SUWindowController 10 | LANGUAGE 11 | ObjC 12 | SUPERCLASS 13 | NSWindowController 14 | 15 | 16 | CLASS 17 | NSApplication 18 | LANGUAGE 19 | ObjC 20 | SUPERCLASS 21 | NSResponder 22 | 23 | 24 | ACTIONS 25 | 26 | installUpdate 27 | id 28 | remindMeLater 29 | id 30 | skipThisVersion 31 | id 32 | 33 | CLASS 34 | SUUpdateAlert 35 | LANGUAGE 36 | ObjC 37 | OUTLETS 38 | 39 | delegate 40 | id 41 | description 42 | NSTextField 43 | releaseNotesView 44 | WebView 45 | 46 | SUPERCLASS 47 | SUWindowController 48 | 49 | 50 | CLASS 51 | FirstResponder 52 | LANGUAGE 53 | ObjC 54 | SUPERCLASS 55 | NSObject 56 | 57 | 58 | CLASS 59 | NSObject 60 | LANGUAGE 61 | ObjC 62 | 63 | 64 | IBVersion 65 | 1 66 | 67 | 68 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRUser.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRUser.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/4/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRUser.h" 10 | #import "EGOCache.h" 11 | 12 | NSString *const RCRTopicPropertyNamedGravatar = @"user.gravatar"; 13 | 14 | @implementation RCRUser 15 | 16 | static NSOperationQueue *sharedGravatarOperationQueue() { 17 | static NSOperationQueue *sharedGravatarOperationQueue = nil; 18 | if (sharedGravatarOperationQueue == nil) { 19 | sharedGravatarOperationQueue = [[NSOperationQueue alloc] init]; 20 | } 21 | return sharedGravatarOperationQueue; 22 | } 23 | 24 | - (NSURL *)gravatarUrl { 25 | if (self.avatarUrl.length > 0) { 26 | return [NSURL URLWithString:self.avatarUrl]; 27 | } 28 | 29 | return [NSURL URLWithString:[NSString stringWithFormat:@"http://gravatar.com/avatar/%@.png?s=48", self.gravatarHash]]; 30 | } 31 | 32 | - (NSString *)avatarCacheKey { 33 | NSInteger hash = [[[[self gravatarUrl] absoluteString] description] hash]; 34 | return [NSString stringWithFormat:@"avatar-image-%ld", hash]; 35 | } 36 | 37 | - (void)loadGravatar { 38 | @synchronized (self) { 39 | if (self.gravatar == nil && !self.loadingGravatar) { 40 | __block NSImage *image = [[EGOCache currentCache] imageForKey:[self avatarCacheKey]]; 41 | if (image) { 42 | @synchronized (self) { 43 | self.loadingGravatar = NO; 44 | self.gravatar = image; 45 | } 46 | } else { 47 | self.loadingGravatar = YES; 48 | [sharedGravatarOperationQueue() addOperationWithBlock:^(void) { 49 | image = [[NSImage alloc] initWithContentsOfURL:[self gravatarUrl]]; 50 | if (image) { 51 | @synchronized (self) { 52 | self.loadingGravatar = NO; 53 | self.gravatar = image; 54 | [[EGOCache currentCache] setImage:image forKey:[self avatarCacheKey] withTimeoutInterval:60 * 60 * 24 * 7]; 55 | } 56 | } else { 57 | @synchronized (self) { 58 | self.gravatar = [NSImage imageNamed:NSImageNameTrashFull]; 59 | } 60 | } 61 | }]; 62 | } 63 | } 64 | } 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRPrefsController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRPrefsController.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/12/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRPrefsController.h" 10 | #import "RCRAccountViewController.h" 11 | #import "RCROptionsViewController.h" 12 | #import "RCRInfoViewController.h" 13 | 14 | @interface RCRPrefsController () { 15 | RCRAccountViewController *accountViewController; 16 | RCROptionsViewController *optionsViewController; 17 | RCRInfoViewController *infoViewController; 18 | } 19 | @end 20 | 21 | @implementation RCRPrefsController 22 | 23 | - (id)initWithWindow:(NSWindow *)window 24 | { 25 | self = [super initWithWindow:window]; 26 | if (self) { 27 | } 28 | 29 | return self; 30 | } 31 | 32 | - (void)windowDidLoad 33 | { 34 | [super windowDidLoad]; 35 | [self.window setStyleMask:self.window.styleMask & ~NSMiniaturizableWindowMask]; 36 | } 37 | 38 | - (void)setupToolbar { 39 | optionsViewController = [[RCROptionsViewController alloc] init]; 40 | [self addView:optionsViewController.view label:optionsViewController.title image:[optionsViewController image]]; 41 | 42 | accountViewController = [[RCRAccountViewController alloc] init]; 43 | [self addView:accountViewController.view label:accountViewController.title image:[accountViewController image]]; 44 | 45 | infoViewController = [[RCRInfoViewController alloc] init]; 46 | [self addView:infoViewController.view label:infoViewController.title image:[infoViewController image]]; 47 | } 48 | 49 | - (void)selectViewWithTitle:(NSString *)title { 50 | for (NSToolbarItem *item in self.window.toolbar.items) { 51 | if ([item.itemIdentifier isEqualToString:title]) { 52 | [self toggleActivePreferenceView:item]; 53 | [self.window.toolbar setSelectedItemIdentifier:item.itemIdentifier]; 54 | return; 55 | } 56 | } 57 | } 58 | 59 | - (void)showPreferences { 60 | if (![self.window isVisible]) { 61 | [self showWindow:nil]; 62 | } 63 | [self.window makeKeyAndOrderFront:nil]; 64 | } 65 | 66 | - (void)showAbout { 67 | if (![self.window isVisible]) { 68 | [self showWindow:nil]; 69 | } 70 | [self.window makeKeyAndOrderFront:nil]; 71 | [self selectViewWithTitle:infoViewController.title]; 72 | } 73 | 74 | - (void)showAccount { 75 | if (![self.window isVisible]) { 76 | [self showWindow:nil]; 77 | } 78 | [self.window makeKeyAndOrderFront:nil]; 79 | [self selectViewWithTitle:accountViewController.title]; 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRSettingsManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRSettingsManager.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/13/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRSettingsManager.h" 10 | #import "EMKeychain.h" 11 | 12 | @implementation RCRSettingsManager 13 | 14 | NSString *const KeychainService = @"RubyChina"; 15 | NSString *const KeychainUsername = @"PrivateToken"; 16 | NSString *const LastTimeRefreshed = @"LastTimeRefreshed"; 17 | NSString *const RefreshInterval = @"RefreshInterval"; 18 | const NSInteger MinRefreshInterval = 60 * 3; 19 | const NSInteger DefaultRefreshInterval = 3600; 20 | 21 | SYNTHESIZE_SINGLETON_FOR_CLASS(RCRSettingsManager); 22 | 23 | @synthesize startAtLogin; 24 | 25 | - (void)setPrivateToken:(NSString *)privateToken { 26 | if (privateToken && privateToken.length > 0) { 27 | EMGenericKeychainItem *keychainItem = [EMGenericKeychainItem genericKeychainItemForService:KeychainService 28 | withUsername:KeychainUsername]; 29 | if (!keychainItem) { 30 | [EMGenericKeychainItem addGenericKeychainItemForService:KeychainService 31 | withUsername:KeychainUsername 32 | password:privateToken]; 33 | } else { 34 | keychainItem.password = privateToken; 35 | } 36 | } 37 | } 38 | 39 | - (NSString *)privateToken { 40 | EMGenericKeychainItem *keychainItem = [EMGenericKeychainItem genericKeychainItemForService:KeychainService 41 | withUsername:KeychainUsername]; 42 | 43 | if (keychainItem) { 44 | return keychainItem.password; 45 | } 46 | return @""; 47 | } 48 | 49 | - (NSInteger)minRefreshInterval { 50 | return MinRefreshInterval; 51 | } 52 | 53 | - (NSTimeInterval)lastTimeRefreshed { 54 | return [[NSUserDefaults standardUserDefaults] doubleForKey:LastTimeRefreshed]; 55 | } 56 | 57 | - (void)setLastTimeRefreshed:(NSTimeInterval)lastTime { 58 | [[NSUserDefaults standardUserDefaults] setDouble:lastTime forKey:LastTimeRefreshed]; 59 | [[NSUserDefaults standardUserDefaults] synchronize]; 60 | } 61 | 62 | - (NSInteger)refreshInterval { 63 | NSInteger interval = [[NSUserDefaults standardUserDefaults] integerForKey:RefreshInterval]; 64 | return interval > 0 ? interval : DefaultRefreshInterval; 65 | } 66 | 67 | - (void)setRefreshInterval:(NSInteger)interval { 68 | [[NSUserDefaults standardUserDefaults] setInteger:interval forKey:RefreshInterval]; 69 | [[NSUserDefaults standardUserDefaults] synchronize]; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRAppDelegate.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 2/28/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RCRAppDelegate.h" 11 | #import "RCRAppController.h" 12 | #import "RCRPrefsController.h" 13 | #import "RCRUser.h" 14 | #import "RCRTopic.h" 15 | #import "RCRNode.h" 16 | 17 | @interface RCRAppDelegate () { 18 | } 19 | 20 | - (void)mapObjects; 21 | @end 22 | 23 | @implementation RCRAppDelegate 24 | 25 | /* 26 | #ifdef DEBUG 27 | static NSString * API_ENDPOINT = @"http://localhost:3000"; 28 | #else 29 | */ 30 | static NSString * API_ENDPOINT = @"http://ruby-china.org"; 31 | //#endif 32 | 33 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 34 | { 35 | [self mapObjects]; 36 | 37 | [[RCRAppController sharedAppController] showWindow:nil]; 38 | } 39 | 40 | #pragma mark - Actions 41 | 42 | - (IBAction)aboutClicked:(id)sender { 43 | [(RCRPrefsController *)[RCRPrefsController sharedPrefsWindowController] showAbout]; 44 | } 45 | 46 | - (IBAction)preferencesClicked:(id)sender { 47 | [(RCRPrefsController *)[RCRPrefsController sharedPrefsWindowController] showPreferences]; 48 | } 49 | 50 | - (IBAction)showMainWindow:(id)sender { 51 | [[RCRAppController sharedAppController] showMainWindow]; 52 | } 53 | 54 | - (IBAction)closeWindow:(id)sender { 55 | [[NSApp keyWindow] close]; 56 | } 57 | 58 | - (IBAction)newTopicClicked:(id)sender { 59 | [[RCRAppController sharedAppController] newTopic]; 60 | } 61 | 62 | #pragma mark - Private Methods 63 | 64 | - (void)mapObjects { 65 | RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:API_ENDPOINT]]; 66 | 67 | RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[RCRUser class]]; 68 | [userMapping addAttributeMappingsFromArray:@[@"login", @"name", @"location", @"bio", @"tagline", @"website"]]; 69 | [userMapping addAttributeMappingsFromDictionary:@{ 70 | @"github_url": @"githubUrl", 71 | @"gravatar_hash": @"gravatarHash", 72 | @"avatar_url": @"avatarUrl" 73 | }]; 74 | [manager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:userMapping pathPattern:nil keyPath:nil statusCodes:nil]]; 75 | 76 | RKObjectMapping *topicMapping = [RKObjectMapping mappingForClass:[RCRTopic class]]; 77 | [topicMapping addAttributeMappingsFromDictionary:@{ 78 | @"title": @"title", 79 | @"id": @"topicId", 80 | //@"body": @"body", 81 | //@"body_html": @"bodyHtml", 82 | @"replies_count": @"repliesCount", 83 | @"created_at": @"createdDate", 84 | @"updated_at": @"updatedDate", 85 | @"replied_at": @"repliedAt", 86 | @"node_name": @"nodeName", 87 | @"node_id": @"nodeId", 88 | @"last_reply_user_login": @"lastReplyUserLogin" 89 | }]; 90 | [topicMapping addRelationshipMappingWithSourceKeyPath:@"user" mapping:userMapping]; 91 | [manager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:topicMapping pathPattern:nil keyPath:nil statusCodes:nil]]; 92 | 93 | RKObjectMapping *nodeMapping = [RKObjectMapping mappingForClass:[RCRNode class]]; 94 | [nodeMapping addAttributeMappingsFromDictionary:@{ 95 | @"_id": @"nodeId", 96 | @"name": @"name" 97 | }]; 98 | [manager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:topicMapping pathPattern:nil keyPath:nil statusCodes:nil]]; 99 | } 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRTableRowView.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRTableRowView.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/4/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRTableRowView.h" 10 | 11 | @interface RCRTableRowView () { 12 | BOOL mouseInside; 13 | NSTrackingArea *trackingArea; 14 | } 15 | @property BOOL mouseInside; 16 | @end 17 | 18 | @implementation RCRTableRowView 19 | 20 | @synthesize objectValue; 21 | @dynamic mouseInside; 22 | 23 | - (void)setMouseInside:(BOOL)value { 24 | if (mouseInside != value) { 25 | mouseInside = value; 26 | [self setNeedsDisplay:YES]; 27 | } 28 | } 29 | 30 | - (BOOL)mouseInside { 31 | return mouseInside; 32 | } 33 | 34 | - (void)mouseEntered:(NSEvent *)theEvent { 35 | self.mouseInside = YES; 36 | } 37 | 38 | - (void)mouseExited:(NSEvent *)theEvent { 39 | self.mouseInside = NO; 40 | } 41 | 42 | - (void)ensureTrackingArea { 43 | if (trackingArea == nil) { 44 | trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect options:NSTrackingInVisibleRect | NSTrackingActiveAlways | NSTrackingMouseEnteredAndExited owner:self userInfo:nil]; 45 | } 46 | } 47 | 48 | - (void)updateTrackingAreas { 49 | [super updateTrackingAreas]; 50 | [self ensureTrackingArea]; 51 | if (![[self trackingAreas] containsObject:trackingArea]) { 52 | [self addTrackingArea:trackingArea]; 53 | } 54 | } 55 | 56 | static NSGradient *gradientWithTargetColor(NSColor *targetColor) { 57 | NSArray *colors = [NSArray arrayWithObjects:[targetColor colorWithAlphaComponent:0], targetColor, targetColor, [targetColor colorWithAlphaComponent:0], nil]; 58 | const CGFloat locations[4] = { 0.0, 0.35, 0.65, 1.0 }; 59 | return [[NSGradient alloc] initWithColors:colors atLocations:locations colorSpace:[NSColorSpace sRGBColorSpace]]; 60 | } 61 | 62 | void DrawSeparatorInRect(NSRect rect) { 63 | static NSGradient *gradient = nil; 64 | if (gradient == nil) { 65 | gradient = gradientWithTargetColor([NSColor colorWithSRGBRed:.80 green:.80 blue:.80 alpha:1]); 66 | } 67 | [gradient drawInRect:rect angle:0]; 68 | 69 | } 70 | - (NSRect)separatorRect { 71 | NSRect separatorRect = self.bounds; 72 | separatorRect.origin.y = NSMaxY(separatorRect) - 1; 73 | separatorRect.size.height = 1; 74 | return separatorRect; 75 | } 76 | 77 | - (void)drawSeparatorInRect:(NSRect)dirtyRect { 78 | DrawSeparatorInRect([self separatorRect]); 79 | } 80 | 81 | - (void)drawSelectionInRect:(NSRect)dirtyRect { 82 | if (self.selectionHighlightStyle != NSTableViewSelectionHighlightStyleNone) { 83 | NSRect selectionRect = NSInsetRect(self.bounds, 0, 0.2); 84 | [[NSColor colorWithCalibratedWhite:.82 alpha:1.0] setFill]; 85 | NSBezierPath *selectionPath = [NSBezierPath bezierPathWithRoundedRect:selectionRect xRadius:1 yRadius:1]; 86 | [selectionPath fill]; 87 | } 88 | } 89 | 90 | - (void)drawBackgroundInRect:(NSRect)dirtyRect { 91 | [self.backgroundColor set]; 92 | NSRectFill(self.bounds); 93 | 94 | if (self.mouseInside) { 95 | NSGradient *gradient = gradientWithTargetColor([NSColor colorWithCalibratedWhite:.82 alpha:1.0]); 96 | [gradient drawInRect:self.bounds angle:0]; 97 | } 98 | } 99 | 100 | - (NSBackgroundStyle)interiorBackgroundStyle { 101 | return NSBackgroundStyleLight; 102 | } 103 | 104 | - (void)setFrame:(NSRect)frameRect { 105 | [super setFrame:frameRect]; 106 | if ([self inLiveResize]) { 107 | if (self.selected) { 108 | [self setNeedsDisplay:YES]; 109 | } else { 110 | [self setNeedsDisplayInRect:[self separatorRect]]; 111 | } 112 | } 113 | } 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /RubyChinaReader/Preferences.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1070 5 | 11D50 6 | 2182 7 | 1138.32 8 | 568.00 9 | 10 | com.apple.InterfaceBuilder.CocoaPlugin 11 | 2182 12 | 13 | 14 | NSCustomObject 15 | 16 | 17 | com.apple.InterfaceBuilder.CocoaPlugin 18 | 19 | 20 | PluginDependencyRecalculationVersion 21 | 22 | 23 | 24 | 25 | NSObject 26 | 27 | 28 | FirstResponder 29 | 30 | 31 | NSApplication 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 0 40 | 41 | 42 | 43 | 44 | 45 | -2 46 | 47 | 48 | File's Owner 49 | 50 | 51 | -1 52 | 53 | 54 | First Responder 55 | 56 | 57 | -3 58 | 59 | 60 | Application 61 | 62 | 63 | 64 | 65 | com.apple.InterfaceBuilder.CocoaPlugin 66 | com.apple.InterfaceBuilder.CocoaPlugin 67 | com.apple.InterfaceBuilder.CocoaPlugin 68 | 69 | 70 | 71 | 72 | 73 | 0 74 | 75 | 76 | 0 77 | IBCocoaFramework 78 | YES 79 | 3 80 | YES 81 | 82 | 83 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Headers/SUUpdater.h: -------------------------------------------------------------------------------- 1 | // 2 | // SUUpdater.h 3 | // Sparkle 4 | // 5 | // Created by Andy Matuschak on 1/4/06. 6 | // Copyright 2006 Andy Matuschak. All rights reserved. 7 | // 8 | 9 | #ifndef SUUPDATER_H 10 | #define SUUPDATER_H 11 | 12 | #import 13 | 14 | @class SUUpdateDriver, SUAppcastItem, SUHost, SUAppcast; 15 | @interface SUUpdater : NSObject { 16 | NSTimer *checkTimer; 17 | SUUpdateDriver *driver; 18 | 19 | SUHost *host; 20 | IBOutlet id delegate; 21 | } 22 | 23 | + (SUUpdater *)sharedUpdater; 24 | + (SUUpdater *)updaterForBundle:(NSBundle *)bundle; 25 | - (NSBundle *)hostBundle; 26 | 27 | - (void)setDelegate:(id)delegate; 28 | - delegate; 29 | 30 | - (void)setAutomaticallyChecksForUpdates:(BOOL)automaticallyChecks; 31 | - (BOOL)automaticallyChecksForUpdates; 32 | 33 | - (void)setUpdateCheckInterval:(NSTimeInterval)interval; 34 | - (NSTimeInterval)updateCheckInterval; 35 | 36 | - (void)setFeedURL:(NSURL *)feedURL; 37 | - (NSURL *)feedURL; 38 | 39 | - (void)setSendsSystemProfile:(BOOL)sendsSystemProfile; 40 | - (BOOL)sendsSystemProfile; 41 | 42 | - (void)setAutomaticallyDownloadsUpdates:(BOOL)automaticallyDownloadsUpdates; 43 | - (BOOL)automaticallyDownloadsUpdates; 44 | 45 | // This IBAction is meant for a main menu item. Hook up any menu item to this action, 46 | // and Sparkle will check for updates and report back its findings verbosely. 47 | - (IBAction)checkForUpdates:sender; 48 | 49 | // This kicks off an update meant to be programmatically initiated. That is, it will display no UI unless it actually finds an update, 50 | // in which case it proceeds as usual. If the fully automated updating is turned on, however, this will invoke that behavior, and if an 51 | // update is found, it will be downloaded and prepped for installation. 52 | - (void)checkForUpdatesInBackground; 53 | 54 | // Date of last update check. Returns null if no check has been performed. 55 | - (NSDate*)lastUpdateCheckDate; 56 | 57 | // This begins a "probing" check for updates which will not actually offer to update to that version. The delegate methods, though, 58 | // (up to updater:didFindValidUpdate: and updaterDidNotFindUpdate:), are called, so you can use that information in your UI. 59 | - (void)checkForUpdateInformation; 60 | 61 | // Call this to appropriately schedule or cancel the update checking timer according to the preferences for time interval and automatic checks. This call does not change the date of the next check, but only the internal NSTimer. 62 | - (void)resetUpdateCycle; 63 | 64 | - (BOOL)updateInProgress; 65 | @end 66 | 67 | @interface NSObject (SUUpdaterDelegateInformalProtocol) 68 | // This method allows you to add extra parameters to the appcast URL, potentially based on whether or not Sparkle will also be sending along the system profile. This method should return an array of dictionaries with keys: "key", "value", "displayKey", "displayValue", the latter two being specifically for display to the user. 69 | - (NSArray *)feedParametersForUpdater:(SUUpdater *)updater sendingSystemProfile:(BOOL)sendingProfile; 70 | 71 | // Use this to override the default behavior for Sparkle prompting the user about automatic update checks. 72 | - (BOOL)updaterShouldPromptForPermissionToCheckForUpdates:(SUUpdater *)bundle; 73 | 74 | // Implement this if you want to do some special handling with the appcast once it finishes loading. 75 | - (void)updater:(SUUpdater *)updater didFinishLoadingAppcast:(SUAppcast *)appcast; 76 | 77 | // If you're using special logic or extensions in your appcast, implement this to use your own logic for finding 78 | // a valid update, if any, in the given appcast. 79 | - (SUAppcastItem *)bestValidUpdateInAppcast:(SUAppcast *)appcast forUpdater:(SUUpdater *)bundle; 80 | 81 | // Sent when a valid update is found by the update driver. 82 | - (void)updater:(SUUpdater *)updater didFindValidUpdate:(SUAppcastItem *)update; 83 | 84 | // Sent when a valid update is not found. 85 | - (void)updaterDidNotFindUpdate:(SUUpdater *)update; 86 | 87 | // Sent immediately before installing the specified update. 88 | - (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update; 89 | 90 | // Return YES to delay the relaunch until you do some processing; invoke the given NSInvocation to continue. 91 | - (BOOL)updater:(SUUpdater *)updater shouldPostponeRelaunchForUpdate:(SUAppcastItem *)update untilInvoking:(NSInvocation *)invocation; 92 | 93 | // Called immediately before relaunching. 94 | - (void)updaterWillRelaunchApplication:(SUUpdater *)updater; 95 | 96 | // This method allows you to provide a custom version comparator. 97 | // If you don't implement this method or return nil, the standard version comparator will be used. 98 | - (id )versionComparatorForUpdater:(SUUpdater *)updater; 99 | 100 | // Returns the path which is used to relaunch the client after the update is installed. By default, the path of the host bundle. 101 | - (NSString *)pathToRelaunchForUpdater:(SUUpdater *)updater; 102 | 103 | @end 104 | 105 | // Define some minimum intervals to avoid DOS-like checking attacks. These are in seconds. 106 | #ifdef DEBUG 107 | #define SU_MIN_CHECK_INTERVAL 60 108 | #else 109 | #define SU_MIN_CHECK_INTERVAL 60*60 110 | #endif 111 | 112 | #ifdef DEBUG 113 | #define SU_DEFAULT_CHECK_INTERVAL 60 114 | #else 115 | #define SU_DEFAULT_CHECK_INTERVAL 60*60*24 116 | #endif 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ADP2,1 6 | Developer Transition Kit 7 | MacBook1,1 8 | MacBook (Core Duo) 9 | MacBook2,1 10 | MacBook (Core 2 Duo) 11 | MacBook4,1 12 | MacBook (Core 2 Duo Feb 2008) 13 | MacBookAir1,1 14 | MacBook Air (January 2008) 15 | MacBookPro1,1 16 | MacBook Pro Core Duo (15-inch) 17 | MacBookPro1,2 18 | MacBook Pro Core Duo (17-inch) 19 | MacBookPro2,1 20 | MacBook Pro Core 2 Duo (17-inch) 21 | MacBookPro2,2 22 | MacBook Pro Core 2 Duo (15-inch) 23 | MacBookPro3,1 24 | MacBook Pro Core 2 Duo (15-inch LED, Core 2 Duo) 25 | MacBookPro3,2 26 | MacBook Pro Core 2 Duo (17-inch HD, Core 2 Duo) 27 | MacBookPro4,1 28 | MacBook Pro (Core 2 Duo Feb 2008) 29 | MacPro1,1 30 | Mac Pro (four-core) 31 | MacPro2,1 32 | Mac Pro (eight-core) 33 | MacPro3,1 34 | Mac Pro (January 2008 4- or 8- core "Harpertown") 35 | Macmini1,1 36 | Mac Mini (Core Solo/Duo) 37 | PowerBook1,1 38 | PowerBook G3 39 | PowerBook2,1 40 | iBook G3 41 | PowerBook2,2 42 | iBook G3 (FireWire) 43 | PowerBook2,3 44 | iBook G3 45 | PowerBook2,4 46 | iBook G3 47 | PowerBook3,1 48 | PowerBook G3 (FireWire) 49 | PowerBook3,2 50 | PowerBook G4 51 | PowerBook3,3 52 | PowerBook G4 (Gigabit Ethernet) 53 | PowerBook3,4 54 | PowerBook G4 (DVI) 55 | PowerBook3,5 56 | PowerBook G4 (1GHz / 867MHz) 57 | PowerBook4,1 58 | iBook G3 (Dual USB, Late 2001) 59 | PowerBook4,2 60 | iBook G3 (16MB VRAM) 61 | PowerBook4,3 62 | iBook G3 Opaque 16MB VRAM, 32MB VRAM, Early 2003) 63 | PowerBook5,1 64 | PowerBook G4 (17 inch) 65 | PowerBook5,2 66 | PowerBook G4 (15 inch FW 800) 67 | PowerBook5,3 68 | PowerBook G4 (17-inch 1.33GHz) 69 | PowerBook5,4 70 | PowerBook G4 (15 inch 1.5/1.33GHz) 71 | PowerBook5,5 72 | PowerBook G4 (17-inch 1.5GHz) 73 | PowerBook5,6 74 | PowerBook G4 (15 inch 1.67GHz/1.5GHz) 75 | PowerBook5,7 76 | PowerBook G4 (17-inch 1.67GHz) 77 | PowerBook5,8 78 | PowerBook G4 (Double layer SD, 15 inch) 79 | PowerBook5,9 80 | PowerBook G4 (Double layer SD, 17 inch) 81 | PowerBook6,1 82 | PowerBook G4 (12 inch) 83 | PowerBook6,2 84 | PowerBook G4 (12 inch, DVI) 85 | PowerBook6,3 86 | iBook G4 87 | PowerBook6,4 88 | PowerBook G4 (12 inch 1.33GHz) 89 | PowerBook6,5 90 | iBook G4 (Early-Late 2004) 91 | PowerBook6,7 92 | iBook G4 (Mid 2005) 93 | PowerBook6,8 94 | PowerBook G4 (12 inch 1.5GHz) 95 | PowerMac1,1 96 | Power Macintosh G3 (Blue & White) 97 | PowerMac1,2 98 | Power Macintosh G4 (PCI Graphics) 99 | PowerMac10,1 100 | Mac Mini G4 101 | PowerMac10,2 102 | Mac Mini (Late 2005) 103 | PowerMac11,2 104 | Power Macintosh G5 (Late 2005) 105 | PowerMac12,1 106 | iMac G5 (iSight) 107 | PowerMac2,1 108 | iMac G3 (Slot-loading CD-ROM) 109 | PowerMac2,2 110 | iMac G3 (Summer 2000) 111 | PowerMac3,1 112 | Power Macintosh G4 (AGP Graphics) 113 | PowerMac3,2 114 | Power Macintosh G4 (AGP Graphics) 115 | PowerMac3,3 116 | Power Macintosh G4 (Gigabit Ethernet) 117 | PowerMac3,4 118 | Power Macintosh G4 (Digital Audio) 119 | PowerMac3,5 120 | Power Macintosh G4 (Quick Silver) 121 | PowerMac3,6 122 | Power Macintosh G4 (Mirrored Drive Door) 123 | PowerMac4,1 124 | iMac G3 (Early/Summer 2001) 125 | PowerMac4,2 126 | iMac G4 (Flat Panel) 127 | PowerMac4,4 128 | eMac 129 | PowerMac4,5 130 | iMac G4 (17-inch Flat Panel) 131 | PowerMac5,1 132 | Power Macintosh G4 Cube 133 | PowerMac6,1 134 | iMac G4 (USB 2.0) 135 | PowerMac6,3 136 | iMac G4 (20-inch Flat Panel) 137 | PowerMac6,4 138 | eMac (USB 2.0, 2005) 139 | PowerMac7,2 140 | Power Macintosh G5 141 | PowerMac7,3 142 | Power Macintosh G5 143 | PowerMac8,1 144 | iMac G5 145 | PowerMac8,2 146 | iMac G5 (Ambient Light Sensor) 147 | PowerMac9,1 148 | Power Macintosh G5 (Late 2005) 149 | RackMac1,1 150 | Xserve G4 151 | RackMac1,2 152 | Xserve G4 (slot-loading, cluster node) 153 | RackMac3,1 154 | Xserve G5 155 | Xserve1,1 156 | Xserve (Intel Xeon) 157 | Xserve2,1 158 | Xserve (January 2008 quad-core) 159 | iMac1,1 160 | iMac G3 (Rev A-D) 161 | iMac4,1 162 | iMac (Core Duo) 163 | iMac4,2 164 | iMac for Education (17-inch, Core Duo) 165 | iMac5,1 166 | iMac (Core 2 Duo, 17 or 20 inch, SuperDrive) 167 | iMac5,2 168 | iMac (Core 2 Duo, 17 inch, Combo Drive) 169 | iMac6,1 170 | iMac (Core 2 Duo, 24 inch, SuperDrive) 171 | iMac8,1 172 | iMac (April 2008) 173 | 174 | 175 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRAppController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRAppController.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 2/28/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRAppController.h" 10 | #import "RCRTopicsViewController.h" 11 | #import "RCRSettingsManager.h" 12 | #import "RCRPrefsController.h" 13 | 14 | @interface RCRAppController() { 15 | RCRTopicsViewController *topicsViewController; 16 | NSView *contentView; 17 | EDSideBar *sideBar; 18 | } 19 | 20 | @end 21 | 22 | @implementation RCRAppController 23 | 24 | const CGFloat SideBarWidth = 65; 25 | const CGFloat DefaultWindowHeight = 650; 26 | const CGFloat DefaultWindowWidth = DefaultWindowHeight * 0.618 - SideBarWidth; 27 | 28 | enum { 29 | RCRSideBarRowTopics = 0, 30 | RCRSideBarRowNotification = 1, 31 | }; 32 | 33 | + (RCRAppController *)sharedAppController{ 34 | static RCRAppController *_sharedAppController = nil; 35 | if(!_sharedAppController){ 36 | _sharedAppController = [[self alloc] initWithWindowNibName:@"MainMenu"]; 37 | } 38 | return _sharedAppController; 39 | } 40 | 41 | - (IBAction)showWindow:(id)sender{ 42 | // This forces the resources in the nib to load. 43 | [self window]; 44 | 45 | [super showWindow:sender]; 46 | } 47 | 48 | - (id)initWithWindow:(NSWindow *)window{ 49 | if((self = [super initWithWindow:nil])){ 50 | } 51 | return self; 52 | } 53 | 54 | - (void)windowDidLoad{ 55 | NSWindow *window = 56 | [[NSWindow alloc] initWithContentRect:NSMakeRect(900, 250, DefaultWindowWidth + SideBarWidth, DefaultWindowHeight) 57 | styleMask:(NSTitledWindowMask | 58 | NSClosableWindowMask | 59 | NSResizableWindowMask | 60 | NSMiniaturizableWindowMask) 61 | backing:NSBackingStoreBuffered 62 | defer:YES]; 63 | window.delegate = self; 64 | [self setWindow:window]; 65 | 66 | contentView = [[NSView alloc] initWithFrame:NSMakeRect(SideBarWidth, 0, DefaultWindowWidth, DefaultWindowHeight)]; 67 | [self.window.contentView addSubview:contentView]; 68 | 69 | [contentView setTranslatesAutoresizingMaskIntoConstraints:NO]; 70 | [self.window.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(==65)-[contentView(>=300)]-(==0)-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(contentView)]]; 71 | [self.window.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[contentView(>=250)]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(contentView)]]; 72 | 73 | sideBar = [[EDSideBar alloc] initWithFrame:NSMakeRect(0, 0, SideBarWidth, DefaultWindowHeight)]; 74 | sideBar.sidebarDelegate = self; 75 | sideBar.layoutMode = ECSideBarLayoutTop; 76 | [self.window.contentView addSubview:sideBar]; 77 | 78 | [sideBar setTranslatesAutoresizingMaskIntoConstraints:NO]; 79 | [self.window.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[sideBar(==65)]-(>=0)-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(sideBar)]]; 80 | [self.window.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[sideBar]-0-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(sideBar)]]; 81 | 82 | topicsViewController = [[RCRTopicsViewController alloc] init]; 83 | NSView *topicsView = topicsViewController.view; 84 | [contentView addSubview:topicsView]; 85 | 86 | [topicsView setTranslatesAutoresizingMaskIntoConstraints:NO]; 87 | [contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[topicsView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(topicsView)]]; 88 | [contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topicsView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(topicsView)]]; 89 | 90 | [sideBar addButtonWithTitle:topicsViewController.title image:[NSImage imageNamed:NSImageNameBonjour]]; 91 | 92 | NSButton *newTopicButton = [[NSButton alloc] init]; 93 | [newTopicButton bind:@"enabled" toObject:topicsViewController withKeyPath:@"canPostTopic" options:nil]; 94 | newTopicButton.bezelStyle = NSThickSquareBezelStyle; 95 | newTopicButton.image = [NSImage imageNamed:NSImageNameAddTemplate]; 96 | newTopicButton.target = self; 97 | newTopicButton.action = @selector(newTopic); 98 | [self.window.contentView addSubview:newTopicButton]; 99 | 100 | [newTopicButton setTranslatesAutoresizingMaskIntoConstraints:NO]; 101 | [self.window.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-8-[newTopicButton(==20)]-(>=0)-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(newTopicButton)]]; 102 | [self.window.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=0)-[newTopicButton(==20)]-4-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(newTopicButton)]]; 103 | 104 | NSButton *refreshButton = [[NSButton alloc] init]; 105 | [refreshButton bind:@"enabled" toObject:topicsViewController withKeyPath:@"canRefresh" options:nil]; 106 | refreshButton.bezelStyle = NSThickSquareBezelStyle; 107 | refreshButton.image = [NSImage imageNamed:NSImageNameRefreshTemplate]; 108 | refreshButton.target = topicsViewController; 109 | refreshButton.action = @selector(refresh); 110 | [self.window.contentView addSubview:refreshButton]; 111 | 112 | [refreshButton setTranslatesAutoresizingMaskIntoConstraints:NO]; 113 | [self.window.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-32-[refreshButton(==20)]-(>=0)-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(refreshButton)]]; 114 | [self.window.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=0)-[refreshButton(==20)]-4-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(refreshButton)]]; 115 | 116 | [sideBar selectButtonAtRow:RCRSideBarRowTopics]; 117 | [topicsViewController start]; 118 | } 119 | 120 | - (void)showMainWindow { 121 | [self showWindow:nil]; 122 | } 123 | 124 | #pragma mark - EDSlidebarDelegate 125 | 126 | - (void)sideBar:(EDSideBar*)tabBar didSelectButton:(NSInteger)index { 127 | } 128 | 129 | #pragma mark - NSWindowDelegate 130 | - (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize { 131 | if (frameSize.width > 800) { 132 | frameSize.width = 800; 133 | } 134 | return frameSize; 135 | } 136 | 137 | #pragma mark - private methods 138 | 139 | - (void)newTopic { 140 | if ([RCRSettingsManager sharedRCRSettingsManager].privateToken.length == 0) { 141 | NSAlert *alert = [NSAlert alertWithMessageText:@"尚未设置密钥" 142 | defaultButton:@"设置密钥" 143 | alternateButton:@"太麻烦,不玩了" 144 | otherButton:nil 145 | informativeTextWithFormat:@"发帖、查看通知等需要使用个人密钥。密钥会保存到 Keychain 中。"]; 146 | [alert beginSheetModalForWindow:self.window modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:nil]; 147 | } else { 148 | [topicsViewController newTopic:nil]; 149 | } 150 | } 151 | 152 | - (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { 153 | if (returnCode == NSAlertDefaultReturn) { 154 | [(RCRPrefsController *)[RCRPrefsController sharedPrefsWindowController] showAccount]; 155 | } 156 | } 157 | 158 | @end 159 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRTopicsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCRTopicsViewController.m 3 | // RubyChinaReader 4 | // 5 | // Created by James Chen on 3/3/12. 6 | // Copyright (c) 2012 ashchan.com. All rights reserved. 7 | // 8 | 9 | #import "RCRTopicsViewController.h" 10 | #import "RCRTableRowView.h" 11 | #import "RCRTopicCellView.h" 12 | #import "RCRTopic.h" 13 | #import "RCRUserDetailViewController.h" 14 | #import "RCRUrlBuilder.h" 15 | #import "RCRSettingsManager.h" 16 | #import "RCRNode.h" 17 | 18 | @interface RCRTopicsViewController () { 19 | NSArray *_topics; 20 | NSArray *_nodes; 21 | NSMutableArray *_observedVisibleItems; 22 | NSPopover *_userPopover; 23 | RCRUserDetailViewController *_userDetailViewController; 24 | NSTimer *_uiTimer; // update refresh button 25 | NSTimer *_refreshTimer; 26 | IBOutlet NSTableView *topicsTableView; 27 | IBOutlet NSProgressIndicator *loading; 28 | IBOutlet NSWindow *newTopicPanel; 29 | IBOutlet NSTextField *newTopicTitle; 30 | IBOutlet NSTextView *newTopicBody; 31 | IBOutlet NSPopUpButton *newTopicNode; 32 | } 33 | 34 | - (void)reloadRowForEntity:(id)object; 35 | - (RCRTopic *)topicForRow:(NSInteger)row; 36 | - (RCRTopic *)topicForId:(NSInteger)topicId; 37 | - (void)closeUserPopover; 38 | - (void)createRefreshTimer; 39 | - (void)fetchNodes; 40 | - (void)clearNewTopic; 41 | 42 | - (IBAction)submitTopic:(id)sender; 43 | 44 | @end 45 | 46 | @implementation RCRTopicsViewController 47 | 48 | NSString *const SELECT_NODE = @"--选择一个节点--"; 49 | 50 | @synthesize canPostTopic; 51 | 52 | - (NSString *)nibName { 53 | return @"RCRTopicsViewController"; 54 | } 55 | 56 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 57 | { 58 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 59 | if (self) { 60 | self.title = @"Topics"; 61 | _userPopover = [[NSPopover alloc] init]; 62 | _userPopover.behavior = NSPopoverBehaviorApplicationDefined; 63 | _userDetailViewController = [[RCRUserDetailViewController alloc] init]; 64 | _userPopover.contentViewController = _userDetailViewController; 65 | _uiTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(uiTimerUpdated) userInfo:nil repeats:YES]; 66 | 67 | [[RCRSettingsManager sharedRCRSettingsManager] addObserver:self forKeyPath:@"refreshInterval" options:NSKeyValueObservingOptionNew context:nil]; 68 | } 69 | 70 | return self; 71 | } 72 | 73 | - (void)start { 74 | // force load nib 75 | [_userDetailViewController view]; 76 | 77 | topicsTableView.hidden = YES; 78 | topicsTableView.target = self; 79 | topicsTableView.doubleAction = @selector(topicRowClicked:); 80 | 81 | [self refresh]; 82 | [self fetchNodes]; 83 | } 84 | 85 | - (void)refresh { 86 | [RCRSettingsManager sharedRCRSettingsManager].lastTimeRefreshed = [[NSDate date] timeIntervalSince1970]; 87 | [self setCanRefresh:NO]; 88 | loading.hidden = NO; 89 | [loading startAnimation:nil]; 90 | 91 | [RKObjectManager.sharedManager getObjectsAtPath:@"/api/topics.json?size=50" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { 92 | _topics = [[mappingResult array] copy]; 93 | topicsTableView.hidden = NO; 94 | [loading stopAnimation:nil]; 95 | loading.hidden = YES; 96 | 97 | [topicsTableView reloadData]; 98 | } failure:^(RKObjectRequestOperation *operation, NSError *error) { 99 | }]; 100 | 101 | [self createRefreshTimer]; 102 | } 103 | 104 | - (BOOL)canRefresh { 105 | return [[NSDate date] timeIntervalSince1970] - [RCRSettingsManager sharedRCRSettingsManager].lastTimeRefreshed >= [RCRSettingsManager sharedRCRSettingsManager].minRefreshInterval; 106 | } 107 | 108 | - (void)setCanRefresh:(BOOL)yesOrNo { 109 | // just trigger KVO 110 | } 111 | 112 | - (void)uiTimerUpdated { 113 | [self setCanRefresh:YES]; 114 | } 115 | 116 | - (void)createRefreshTimer { 117 | [_refreshTimer invalidate]; 118 | _refreshTimer = [NSTimer scheduledTimerWithTimeInterval:[RCRSettingsManager sharedRCRSettingsManager].refreshInterval 119 | target:self 120 | selector:@selector(refreshTimerUpdated) 121 | userInfo:nil 122 | repeats:YES]; 123 | } 124 | 125 | - (void)refreshTimerUpdated { 126 | [self refresh]; 127 | } 128 | 129 | #pragma mark - RKRequestDelegate 130 | /* 131 | - (void)request:(RKRequest *)request didLoadResponse:(RKResponse *)response { 132 | if (response.statusCode == 201) { 133 | [self clearNewTopic]; 134 | [NSApp endSheet:newTopicPanel returnCode:NSRunStoppedResponse]; 135 | } 136 | } 137 | */ 138 | 139 | #pragma mark - NSTableViewDelegate 140 | 141 | - (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row { 142 | RCRTableRowView *rowView = [[RCRTableRowView alloc] initWithFrame:NSMakeRect(0, 0, 300, 20)]; 143 | rowView.objectValue = [self topicForRow:row]; 144 | return rowView; 145 | } 146 | 147 | - (void)tableView:(NSTableView *)tableView didRemoveRowView:(RCRTableRowView *)rowView forRow:(NSInteger)row { 148 | RCRTopic *topic = rowView.objectValue; 149 | NSInteger index = [_observedVisibleItems indexOfObject:topic.user]; 150 | if (index != NSNotFound) { 151 | [topic removeObserver:self forKeyPath:RCRTopicPropertyNamedGravatar]; 152 | [_observedVisibleItems removeObjectAtIndex:index]; 153 | } 154 | } 155 | 156 | - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { 157 | RCRTopic *topic = [self topicForRow:row]; 158 | RCRTopicCellView *cellView = [topicsTableView makeViewWithIdentifier:tableColumn.identifier owner:self]; 159 | cellView.textField.stringValue = [NSString stringWithFormat:@"@%@", topic.user.login]; 160 | 161 | NSString *statusText = @""; 162 | if (topic.lastReplyUserLogin.length > 0) { 163 | statusText = [NSString stringWithFormat:@"[%@] 最后由 %@ 回复", topic.nodeName, topic.lastReplyUserLogin]; 164 | } 165 | else { 166 | statusText = [NSString stringWithFormat:@"[%@] 由 %@ 创建", topic.nodeName, topic.user.login]; 167 | } 168 | [cellView.nodeName setTitleWithMnemonic:statusText]; 169 | 170 | if (topic.repliedAt) { 171 | [cellView.repliedAt setTitleWithMnemonic:[topic.repliedAt timeAgo]]; 172 | } else { 173 | [cellView.repliedAt setTitleWithMnemonic:@""]; 174 | } 175 | 176 | cellView.repliesCount.title = topic.repliesCount.stringValue; 177 | [cellView.repliesCount.cell setHighlightsBy:0]; 178 | [cellView.repliesCount.cell setBezelStyle:NSInlineBezelStyle]; 179 | cellView.topicTitle.stringValue = topic.title; 180 | 181 | if (_observedVisibleItems == nil) { 182 | _observedVisibleItems = [NSMutableArray new]; 183 | } 184 | if (![_observedVisibleItems containsObject:topic.user]) { 185 | [topic addObserver:self forKeyPath:RCRTopicPropertyNamedGravatar options:0 context:NULL]; 186 | [topic.user loadGravatar]; 187 | [_observedVisibleItems addObject:topic.user]; 188 | } 189 | 190 | if (topic.user.gravatar == nil) { 191 | [cellView.progressIndicator setHidden:NO]; 192 | [cellView.progressIndicator startAnimation:nil]; 193 | } else { 194 | cellView.gravatarButton.image = topic.user.gravatar; 195 | } 196 | cellView.gravatarButton.tag = topic.topicId.integerValue; 197 | 198 | return cellView; 199 | } 200 | 201 | - (void)tableViewSelectionDidChange:(NSNotification *)notification { 202 | [self closeUserPopover]; 203 | } 204 | 205 | #pragma mark - NSTableViewDataSource 206 | 207 | - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { 208 | return _topics.count; 209 | } 210 | 211 | #pragma mark - Actions 212 | 213 | - (IBAction)userImageClicked:(id)sender { 214 | RCRTopic *topic = [self topicForId:[sender tag]]; 215 | if (topic) { 216 | NSMutableAttributedString *userName = [[NSMutableAttributedString alloc] initWithString:(topic.user.name.length > 0 ? topic.user.name : topic.user.login)]; 217 | NSRange range = NSMakeRange(0, userName.length); 218 | [userName addAttribute:NSLinkAttributeName 219 | value:[RCRUrlBuilder urlWithPath:[NSString stringWithFormat:@"/%@", topic.user.login]] 220 | range:range]; 221 | [userName addAttribute:NSForegroundColorAttributeName 222 | value:[NSColor blueColor] 223 | range:range]; 224 | [userName addAttribute:NSUnderlineStyleAttributeName 225 | value:[NSNumber numberWithInt:NSSingleUnderlineStyle] 226 | range:range]; 227 | _userDetailViewController.name.allowsEditingTextAttributes = YES; 228 | _userDetailViewController.name.attributedStringValue = userName; 229 | 230 | if (topic.user.tagline.length > 0) { 231 | _userDetailViewController.tagline.stringValue = topic.user.tagline; 232 | } else { 233 | _userDetailViewController.tagline.stringValue = @"这哥们儿没签名"; 234 | } 235 | 236 | if (topic.user.location.length > 0){ 237 | [_userDetailViewController.location setHidden:NO]; 238 | _userDetailViewController.location.stringValue = topic.user.location; 239 | } 240 | else{ 241 | [_userDetailViewController.location setHidden:YES]; 242 | } 243 | 244 | [_userPopover showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMaxXEdge]; 245 | } 246 | } 247 | 248 | - (void)topicRowClicked:(id)sender { 249 | RCRTopic *topic = [self topicForRow:[sender clickedRow]]; 250 | [[NSWorkspace sharedWorkspace] openURL:[RCRUrlBuilder urlWithPath:[NSString stringWithFormat:@"/topics/%@", topic.topicId]]]; 251 | } 252 | 253 | - (IBAction)newTopic:(id)sender { 254 | [newTopicNode removeAllItems]; 255 | [newTopicNode addItemWithTitle:SELECT_NODE]; 256 | [newTopicNode lastItem].tag = -1; 257 | for (RCRNode *node in _nodes) { 258 | [newTopicNode addItemWithTitle:node.name]; 259 | [newTopicNode lastItem].tag = node.nodeId.integerValue; 260 | } 261 | 262 | [NSApp beginSheet:newTopicPanel 263 | modalForWindow:[NSApp keyWindow] 264 | modalDelegate:self 265 | didEndSelector:@selector(didEndSheet:returnCode:contextInfo:) 266 | contextInfo:nil]; 267 | } 268 | 269 | - (IBAction)submitTopic:(id)sender { 270 | if ([sender tag] == 1) { 271 | BOOL hasError = NO; 272 | 273 | NSInteger node_id = newTopicNode.selectedTag; 274 | if (newTopicTitle.stringValue.length == 0) { 275 | hasError = YES; 276 | newTopicTitle.backgroundColor = [NSColor redColor]; 277 | } 278 | else { 279 | newTopicTitle.backgroundColor = [NSColor textBackgroundColor]; 280 | } 281 | 282 | if (newTopicBody.string.length == 0) { 283 | hasError = YES; 284 | newTopicBody.backgroundColor = [NSColor redColor]; 285 | } else { 286 | newTopicBody.backgroundColor = [NSColor textBackgroundColor]; 287 | } 288 | 289 | if (node_id == -1) { 290 | hasError = YES; 291 | NSMutableAttributedString *error = [[NSMutableAttributedString alloc] initWithString:SELECT_NODE]; 292 | [error addAttribute:NSBackgroundColorAttributeName value:[NSColor redColor] range:NSMakeRange(0, error.length)]; 293 | newTopicNode.selectedItem.attributedTitle = error; 294 | } else { 295 | [newTopicNode itemAtIndex:0].attributedTitle = nil; 296 | } 297 | 298 | if (!hasError) { 299 | NSDictionary *params = @{ 300 | @"title": newTopicTitle.stringValue, 301 | @"body": newTopicBody.string, 302 | @"node_id": [NSNumber numberWithInteger:newTopicNode.selectedTag], 303 | @"token": [RCRSettingsManager sharedRCRSettingsManager].privateToken 304 | }; 305 | //[[RKClient sharedClient] post:@"/api/topics.json" params:params delegate:self]; 306 | } else { 307 | newTopicPanel.viewsNeedDisplay = YES; 308 | } 309 | } else { 310 | [NSApp endSheet:newTopicPanel returnCode:NSRunAbortedResponse]; 311 | [self clearNewTopic]; 312 | } 313 | } 314 | 315 | - (void)didEndSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { 316 | [newTopicPanel orderOut:self]; 317 | } 318 | 319 | #pragma mark - Private Methods & misc 320 | 321 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 322 | if ([keyPath isEqualToString:RCRTopicPropertyNamedGravatar]) { 323 | [self performSelectorOnMainThread:@selector(reloadRowForEntity:) withObject:object waitUntilDone:NO modes:[NSArray arrayWithObject:NSRunLoopCommonModes]]; 324 | return; 325 | } 326 | 327 | if ([keyPath isEqualToString:@"refreshInterval"]) { 328 | [self createRefreshTimer]; 329 | return; 330 | } 331 | } 332 | 333 | - (void)reloadRowForEntity:(id)object { 334 | NSInteger row = [_topics indexOfObject:object]; 335 | if (row != NSNotFound) { 336 | RCRTopicCellView *cellView = [topicsTableView viewAtColumn:0 row:row makeIfNecessary:NO]; 337 | if (cellView) { 338 | RCRTopic *topic = [self topicForRow:row]; 339 | [NSAnimationContext beginGrouping]; 340 | [[NSAnimationContext currentContext] setDuration:0.8]; 341 | [cellView.gravatarButton setAlphaValue:0]; 342 | cellView.gravatarButton.image = topic.user.gravatar; 343 | [cellView.gravatarButton setHidden:NO]; 344 | [[cellView.gravatarButton animator] setAlphaValue:1.0]; 345 | [cellView.progressIndicator setHidden:YES]; 346 | [NSAnimationContext endGrouping]; 347 | } 348 | } 349 | } 350 | 351 | - (RCRTopic *)topicForRow:(NSInteger)row { 352 | return (RCRTopic *)[_topics objectAtIndex:row]; 353 | } 354 | 355 | - (RCRTopic *)topicForId:(NSInteger)topicId { 356 | for (RCRTopic *topic in _topics) { 357 | if (topic.topicId.integerValue == topicId) { 358 | return topic; 359 | } 360 | } 361 | return nil; 362 | } 363 | 364 | - (void)closeUserPopover { 365 | if (_userPopover.shown) { 366 | [_userPopover close]; 367 | } 368 | } 369 | 370 | - (void)fetchNodes { 371 | [RKObjectManager.sharedManager getObjectsAtPath:@"/api/nodes.json" 372 | parameters:nil 373 | success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { 374 | _nodes = [[mappingResult array] copy]; 375 | //self.canPostTopic = YES; 376 | } 377 | failure:^(RKObjectRequestOperation *operation, NSError *error) { 378 | }]; 379 | } 380 | 381 | - (void)clearNewTopic { 382 | newTopicTitle.stringValue = @""; 383 | newTopicBody.string = @""; 384 | [newTopicNode selectItemAtIndex:0]; 385 | } 386 | 387 | @end 388 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRTopicDetailController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1070 5 | 11D50 6 | 2177 7 | 1138.32 8 | 568.00 9 | 10 | com.apple.InterfaceBuilder.CocoaPlugin 11 | 2177 12 | 13 | 14 | NSView 15 | NSScrollView 16 | NSWindowTemplate 17 | NSTextView 18 | IBNSLayoutConstraint 19 | NSScroller 20 | NSCustomObject 21 | 22 | 23 | com.apple.InterfaceBuilder.CocoaPlugin 24 | 25 | 26 | PluginDependencyRecalculationVersion 27 | 28 | 29 | 30 | 31 | RCRTopicDetailController 32 | 33 | 34 | FirstResponder 35 | 36 | 37 | NSApplication 38 | 39 | 40 | 15 41 | 2 42 | {{196, 240}, {480, 270}} 43 | 544735232 44 | Window 45 | NSWindow 46 | 47 | 48 | 49 | 50 | 256 51 | 52 | 53 | 54 | 256 55 | 56 | 57 | 58 | 2304 59 | 60 | 61 | 62 | 2322 63 | 64 | Apple HTML pasteboard type 65 | Apple PDF pasteboard type 66 | Apple PICT pasteboard type 67 | Apple PNG pasteboard type 68 | Apple URL pasteboard type 69 | CorePasteboardFlavorType 0x6D6F6F76 70 | NSColor pasteboard type 71 | NSFilenamesPboardType 72 | NSStringPboardType 73 | NeXT Encapsulated PostScript v1.2 pasteboard type 74 | NeXT RTFD pasteboard type 75 | NeXT Rich Text Format v1.0 pasteboard type 76 | NeXT TIFF v4.0 pasteboard type 77 | NeXT font pasteboard type 78 | NeXT ruler pasteboard type 79 | WebURLsWithTitlesPboardType 80 | public.url 81 | 82 | {438, 14} 83 | 84 | 85 | 86 | _NS:13 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 134 99 | 100 | 101 | 102 | 438 103 | 1 104 | 105 | 106 | 67121127 107 | 0 108 | 109 | 110 | 3 111 | MQA 112 | 113 | 114 | 115 | 6 116 | System 117 | selectedTextBackgroundColor 118 | 119 | 3 120 | MC42NjY2NjY2NjY3AA 121 | 122 | 123 | 124 | 6 125 | System 126 | selectedTextColor 127 | 128 | 3 129 | MAA 130 | 131 | 132 | 133 | 134 | 135 | 136 | 1 137 | MCAwIDEAA 138 | 139 | 140 | {8, -8} 141 | 13 142 | 143 | 144 | 145 | 146 | 147 | 1 148 | 149 | 6 150 | {480, 10000000} 151 | {223, 5} 152 | 153 | 154 | 155 | {{1, 1}, {438, 228}} 156 | 157 | 158 | 159 | _NS:11 160 | 161 | 162 | 163 | {4, 5} 164 | 165 | 79691776 166 | 167 | 168 | 169 | 170 | 171 | file://localhost/Applications/Xcode.app/Contents/SharedFrameworks/DVTKit.framework/Resources/DVTIbeamCursor.tiff 172 | 173 | 174 | 175 | 176 | 3 177 | MCAwAA 178 | 179 | 180 | 181 | 4 182 | 183 | 184 | 185 | 256 186 | {{424, 1}, {15, 228}} 187 | 188 | 189 | _NS:84 190 | 191 | _doScroller: 192 | 1 193 | 0.85256409645080566 194 | 195 | 196 | 197 | -2147483392 198 | {{-100, -100}, {87, 18}} 199 | 200 | 201 | 202 | _NS:33 203 | 1 204 | 205 | _doScroller: 206 | 1 207 | 0.94565218687057495 208 | 209 | 210 | {{20, 20}, {440, 230}} 211 | 212 | 213 | 214 | _NS:9 215 | 133138 216 | 217 | 218 | 219 | 220 | 221 | {480, 270} 222 | 223 | 224 | 225 | {{0, 0}, {1440, 878}} 226 | {10000000000000, 10000000000000} 227 | YES 228 | 229 | 230 | 231 | 232 | 233 | 234 | window 235 | 236 | 237 | 238 | 3 239 | 240 | 241 | 242 | topicView 243 | 244 | 245 | 246 | 17 247 | 248 | 249 | 250 | delegate 251 | 252 | 253 | 254 | 4 255 | 256 | 257 | 258 | 259 | 260 | 0 261 | 262 | 263 | 264 | 265 | 266 | -2 267 | 268 | 269 | File's Owner 270 | 271 | 272 | -1 273 | 274 | 275 | First Responder 276 | 277 | 278 | -3 279 | 280 | 281 | Application 282 | 283 | 284 | 1 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 2 293 | 294 | 295 | 296 | 297 | 298 | 6 299 | 0 300 | 301 | 6 302 | 1 303 | 304 | 20 305 | 306 | 1000 307 | 8 308 | 29 309 | 3 310 | 311 | 312 | 313 | 314 | 3 315 | 0 316 | 317 | 3 318 | 1 319 | 320 | 20 321 | 322 | 1000 323 | 8 324 | 29 325 | 3 326 | 327 | 328 | 329 | 330 | 4 331 | 0 332 | 333 | 4 334 | 1 335 | 336 | 20 337 | 338 | 1000 339 | 8 340 | 29 341 | 3 342 | 343 | 344 | 345 | 346 | 5 347 | 0 348 | 349 | 5 350 | 1 351 | 352 | 20 353 | 354 | 1000 355 | 8 356 | 29 357 | 3 358 | 359 | 360 | 361 | 362 | 363 | 364 | 5 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 6 375 | 376 | 377 | 378 | 379 | 7 380 | 381 | 382 | 383 | 384 | 8 385 | 386 | 387 | 388 | 389 | 36 390 | 391 | 392 | 393 | 394 | 37 395 | 396 | 397 | 398 | 399 | 38 400 | 401 | 402 | 403 | 404 | 39 405 | 406 | 407 | 408 | 409 | 410 | 411 | com.apple.InterfaceBuilder.CocoaPlugin 412 | com.apple.InterfaceBuilder.CocoaPlugin 413 | com.apple.InterfaceBuilder.CocoaPlugin 414 | com.apple.InterfaceBuilder.CocoaPlugin 415 | {{357, 418}, {480, 270}} 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | com.apple.InterfaceBuilder.CocoaPlugin 424 | com.apple.InterfaceBuilder.CocoaPlugin 425 | com.apple.InterfaceBuilder.CocoaPlugin 426 | com.apple.InterfaceBuilder.CocoaPlugin 427 | com.apple.InterfaceBuilder.CocoaPlugin 428 | 429 | com.apple.InterfaceBuilder.CocoaPlugin 430 | com.apple.InterfaceBuilder.CocoaPlugin 431 | com.apple.InterfaceBuilder.CocoaPlugin 432 | com.apple.InterfaceBuilder.CocoaPlugin 433 | 434 | 435 | 436 | 437 | 438 | 39 439 | 440 | 441 | 442 | 443 | NSLayoutConstraint 444 | NSObject 445 | 446 | IBProjectSource 447 | ./Classes/NSLayoutConstraint.h 448 | 449 | 450 | 451 | RCRTopicDetailController 452 | NSWindowController 453 | 454 | topicView 455 | NSTextView 456 | 457 | 458 | topicView 459 | 460 | topicView 461 | NSTextView 462 | 463 | 464 | 465 | IBProjectSource 466 | ./Classes/RCRTopicDetailController.h 467 | 468 | 469 | 470 | 471 | 0 472 | IBCocoaFramework 473 | YES 474 | 3 475 | YES 476 | 477 | 478 | -------------------------------------------------------------------------------- /RubyChinaReader/RCRUserDetailViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1070 5 | 11D50 6 | 2182 7 | 1138.32 8 | 568.00 9 | 10 | com.apple.InterfaceBuilder.CocoaPlugin 11 | 2182 12 | 13 | 14 | NSCustomView 15 | NSTextField 16 | NSTextFieldCell 17 | IBNSLayoutConstraint 18 | NSCustomObject 19 | 20 | 21 | com.apple.InterfaceBuilder.CocoaPlugin 22 | 23 | 24 | PluginDependencyRecalculationVersion 25 | 26 | 27 | 28 | 29 | RCRUserDetailViewController 30 | 31 | 32 | FirstResponder 33 | 34 | 35 | NSApplication 36 | 37 | 38 | 39 | 268 40 | 41 | 42 | 43 | 268 44 | {{174, 47}, {65, 17}} 45 | 46 | 47 | 48 | _NS:1505 49 | YES 50 | 51 | 68288064 52 | 71304192 53 | Location 54 | 55 | LucidaGrande 56 | 13 57 | 1044 58 | 59 | _NS:1505 60 | 61 | 62 | 6 63 | System 64 | controlColor 65 | 66 | 3 67 | MC42NjY2NjY2NjY3AA 68 | 69 | 70 | 71 | 6 72 | System 73 | controlTextColor 74 | 75 | 3 76 | MAA 77 | 78 | 79 | 80 | 81 | 82 | 83 | 268 84 | {{5, 47}, {110, 17}} 85 | 86 | 87 | 88 | _NS:1505 89 | YES 90 | 91 | 70385217 92 | 272630784 93 | Name 94 | 95 | LucidaGrande-Bold 96 | 13 97 | 2072 98 | 99 | _NS:1505 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 268 108 | {{5, 5}, {234, 34}} 109 | 110 | 111 | _NS:9 112 | {250, 750} 113 | YES 114 | 115 | 67239424 116 | 272892160 117 | 这哥们儿没签名 118 | 119 | HiraginoSansGB-W3 120 | 13 121 | 16 122 | 123 | _NS:9 124 | 125 | 126 | 127 | 6 128 | System 129 | headerTextColor 130 | 131 | 132 | 133 | 134 | 135 | {243, 67} 136 | 137 | 138 | 139 | NSView 140 | 141 | 142 | 143 | 144 | 145 | 146 | view 147 | 148 | 149 | 150 | 2 151 | 152 | 153 | 154 | tagline 155 | 156 | 157 | 158 | 16 159 | 160 | 161 | 162 | name 163 | 164 | 165 | 166 | 31 167 | 168 | 169 | 170 | location 171 | 172 | 173 | 174 | 123 175 | 176 | 177 | 178 | 179 | 180 | 0 181 | 182 | 183 | 184 | 185 | 186 | -2 187 | 188 | 189 | File's Owner 190 | 191 | 192 | -1 193 | 194 | 195 | First Responder 196 | 197 | 198 | -3 199 | 200 | 201 | Application 202 | 203 | 204 | 1 205 | 206 | 207 | 208 | 209 | 210 | 211 | 3 212 | 0 213 | 214 | 3 215 | 1 216 | 217 | 3 218 | 219 | 1000 220 | 3 221 | 9 222 | 3 223 | 224 | 225 | 226 | 227 | 11 228 | 0 229 | 230 | 11 231 | 1 232 | 233 | 0.0 234 | 235 | 1000 236 | 6 237 | 24 238 | 2 239 | 240 | 241 | 242 | 243 | 6 244 | 0 245 | 246 | 6 247 | 1 248 | 249 | 0.0 250 | 251 | 1000 252 | 6 253 | 24 254 | 2 255 | 256 | 257 | 258 | 259 | 5 260 | 0 261 | 262 | 5 263 | 1 264 | 265 | 8 266 | 267 | 1000 268 | 3 269 | 9 270 | 3 271 | 272 | 273 | 274 | 275 | 276 | 5 277 | 0 278 | 279 | 5 280 | 1 281 | 282 | 0.0 283 | 284 | 1000 285 | 6 286 | 24 287 | 2 288 | 289 | 290 | 291 | 292 | 3 293 | 0 294 | 295 | 4 296 | 1 297 | 298 | 8 299 | 300 | 1000 301 | 6 302 | 24 303 | 3 304 | 305 | 306 | 307 | 308 | 309 | 310 | 3 311 | 312 | 313 | 314 | 315 | 316 | 7 317 | 0 318 | 319 | 0 320 | 1 321 | 322 | 228 323 | 324 | 1000 325 | 3 326 | 9 327 | 1 328 | 329 | 330 | 331 | 332 | 8 333 | 0 334 | 335 | 0 336 | 1 337 | 338 | 34 339 | 340 | 1000 341 | 3 342 | 9 343 | 1 344 | 345 | 346 | 347 | 348 | 349 | 350 | 4 351 | 352 | 353 | 354 | 355 | 19 356 | 357 | 358 | 359 | 360 | 361 | 7 362 | 0 363 | 364 | 0 365 | 1 366 | 367 | 104 368 | 369 | 1000 370 | 3 371 | 9 372 | 1 373 | 374 | 375 | 376 | 377 | 378 | 379 | 20 380 | 381 | 382 | 383 | 384 | 69 385 | 386 | 387 | 388 | 389 | 390 | 7 391 | 0 392 | 393 | 0 394 | 1 395 | 396 | 59 397 | 398 | 1000 399 | 3 400 | 9 401 | 1 402 | 403 | 404 | 405 | 406 | 407 | 408 | 70 409 | 410 | 411 | 412 | 413 | 204 414 | 415 | 416 | 417 | 418 | 209 419 | 420 | 421 | 422 | 423 | 210 424 | 425 | 426 | 427 | 428 | 211 429 | 430 | 431 | 432 | 433 | 213 434 | 435 | 436 | 437 | 438 | 215 439 | 440 | 441 | 442 | 443 | 216 444 | 445 | 446 | 447 | 448 | 217 449 | 450 | 451 | 452 | 453 | 218 454 | 455 | 456 | 457 | 458 | 219 459 | 460 | 461 | 462 | 463 | 464 | 465 | com.apple.InterfaceBuilder.CocoaPlugin 466 | com.apple.InterfaceBuilder.CocoaPlugin 467 | com.apple.InterfaceBuilder.CocoaPlugin 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | com.apple.InterfaceBuilder.CocoaPlugin 477 | 478 | 479 | 480 | 481 | com.apple.InterfaceBuilder.CocoaPlugin 482 | com.apple.InterfaceBuilder.CocoaPlugin 483 | com.apple.InterfaceBuilder.CocoaPlugin 484 | com.apple.InterfaceBuilder.CocoaPlugin 485 | com.apple.InterfaceBuilder.CocoaPlugin 486 | com.apple.InterfaceBuilder.CocoaPlugin 487 | com.apple.InterfaceBuilder.CocoaPlugin 488 | com.apple.InterfaceBuilder.CocoaPlugin 489 | com.apple.InterfaceBuilder.CocoaPlugin 490 | com.apple.InterfaceBuilder.CocoaPlugin 491 | com.apple.InterfaceBuilder.CocoaPlugin 492 | com.apple.InterfaceBuilder.CocoaPlugin 493 | 494 | 495 | 496 | 497 | 498 | com.apple.InterfaceBuilder.CocoaPlugin 499 | com.apple.InterfaceBuilder.CocoaPlugin 500 | 501 | 502 | 503 | 504 | com.apple.InterfaceBuilder.CocoaPlugin 505 | com.apple.InterfaceBuilder.CocoaPlugin 506 | 507 | 508 | 509 | 510 | 511 | 219 512 | 513 | 514 | 515 | 516 | NSLayoutConstraint 517 | NSObject 518 | 519 | IBProjectSource 520 | ./Classes/NSLayoutConstraint.h 521 | 522 | 523 | 524 | RCRUserDetailViewController 525 | NSViewController 526 | 527 | NSTextField 528 | NSTextField 529 | NSTextField 530 | 531 | 532 | 533 | location 534 | NSTextField 535 | 536 | 537 | name 538 | NSTextField 539 | 540 | 541 | tagline 542 | NSTextField 543 | 544 | 545 | 546 | IBProjectSource 547 | ./Classes/RCRUserDetailViewController.h 548 | 549 | 550 | 551 | 552 | 0 553 | IBCocoaFramework 554 | 555 | com.apple.InterfaceBuilder.CocoaPlugin.macosx 556 | 557 | 558 | YES 559 | 3 560 | YES 561 | 562 | 563 | --------------------------------------------------------------------------------