mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2025-02-03 12:27:32 +01:00
Parse enclosures in RSS.
This commit is contained in:
parent
7d68e3322c
commit
fb9a1d610c
@ -19,6 +19,10 @@ public struct ParsedAttachment: Hashable {
|
||||
|
||||
init?(url: String, mimeType: String?, title: String?, sizeInBytes: Int?, durationInSeconds: Int?) {
|
||||
|
||||
if url.isEmpty {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.url = url
|
||||
self.mimeType = mimeType
|
||||
self.title = title
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
@import Foundation;
|
||||
|
||||
@class RSParsedEnclosure;
|
||||
|
||||
@interface RSParsedArticle : NSObject
|
||||
|
||||
@ -22,6 +23,7 @@
|
||||
@property (nonatomic, nullable) NSString *link;
|
||||
@property (nonatomic, nullable) NSString *permalink;
|
||||
@property (nonatomic, nullable) NSString *author;
|
||||
@property (nonatomic, nullable) NSSet<RSParsedEnclosure *> *enclosures;
|
||||
@property (nonatomic, nullable) NSDate *datePublished;
|
||||
@property (nonatomic, nullable) NSDate *dateModified;
|
||||
@property (nonatomic, nonnull) NSDate *dateParsed;
|
||||
|
21
Frameworks/RSParser/Feeds/XML/RSParsedEnclosure.h
Normal file
21
Frameworks/RSParser/Feeds/XML/RSParsedEnclosure.h
Normal file
@ -0,0 +1,21 @@
|
||||
//
|
||||
// RSParsedEnclosure.h
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 12/18/17.
|
||||
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
@import Foundation;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RSParsedEnclosure : NSObject
|
||||
|
||||
@property (nonatomic) NSString *url;
|
||||
@property (nonatomic) NSInteger length;
|
||||
@property (nonatomic, nullable) NSString *mimeType;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
13
Frameworks/RSParser/Feeds/XML/RSParsedEnclosure.m
Normal file
13
Frameworks/RSParser/Feeds/XML/RSParsedEnclosure.m
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// RSParsedEnclosure.m
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 12/18/17.
|
||||
// Copyright © 2017 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RSParsedEnclosure.h"
|
||||
|
||||
@implementation RSParsedEnclosure
|
||||
|
||||
@end
|
@ -41,8 +41,9 @@ private extension RSParsedFeedTransformer {
|
||||
let datePublished = parsedArticle.datePublished
|
||||
let dateModified = parsedArticle.dateModified
|
||||
let authors = parsedAuthors(parsedArticle.author)
|
||||
let attachments = parsedAttachments(parsedArticle.enclosures)
|
||||
|
||||
return ParsedItem(syncServiceID: nil, uniqueID: uniqueID, feedURL: parsedArticle.feedURL, url: url, externalURL: externalURL, title: title, contentHTML: contentHTML, contentText: nil, summary: nil, imageURL: nil, bannerImageURL: nil, datePublished: datePublished, dateModified: dateModified, authors: authors, tags: nil, attachments: nil)
|
||||
return ParsedItem(syncServiceID: nil, uniqueID: uniqueID, feedURL: parsedArticle.feedURL, url: url, externalURL: externalURL, title: title, contentHTML: contentHTML, contentText: nil, summary: nil, imageURL: nil, bannerImageURL: nil, datePublished: datePublished, dateModified: dateModified, authors: authors, tags: nil, attachments: attachments)
|
||||
}
|
||||
|
||||
static func parsedAuthors(_ authorEmailAddress: String?) -> Set<ParsedAuthor>? {
|
||||
@ -53,4 +54,19 @@ private extension RSParsedFeedTransformer {
|
||||
let author = ParsedAuthor(name: nil, url: nil, avatarURL: nil, emailAddress: authorEmailAddress)
|
||||
return Set([author])
|
||||
}
|
||||
|
||||
static func parsedAttachments(_ enclosures: Set<RSParsedEnclosure>?) -> Set<ParsedAttachment>? {
|
||||
|
||||
guard let enclosures = enclosures, !enclosures.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let attachments = enclosures.flatMap { (enclosure) -> ParsedAttachment? in
|
||||
|
||||
let sizeInBytes = enclosure.length > 0 ? enclosure.length : nil
|
||||
return ParsedAttachment(url: enclosure.url, mimeType: enclosure.mimeType, title: nil, sizeInBytes: sizeInBytes, durationInSeconds: nil)
|
||||
}
|
||||
|
||||
return attachments.isEmpty ? nil : Set(attachments)
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
#import <RSParser/NSString+RSParser.h>
|
||||
#import <RSParser/RSDateParser.h>
|
||||
#import <RSParser/ParserData.h>
|
||||
|
||||
#import <RSParser/RSParsedEnclosure.h>
|
||||
|
||||
@interface RSRSSParser () <RSSAXParserDelegate>
|
||||
|
||||
@ -159,6 +159,8 @@ static const NSInteger kTrueLength = 5;
|
||||
static const char *kUppercaseRDF = "RDF";
|
||||
static const NSInteger kUppercaseRDFLength = 4;
|
||||
|
||||
static const char *kEnclosure = "enclosure";
|
||||
static const NSInteger kEnclosureLength = 10;
|
||||
|
||||
#pragma mark - Parsing
|
||||
|
||||
@ -232,6 +234,29 @@ static const NSInteger kUppercaseRDFLength = 4;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addEnclosure {
|
||||
|
||||
NSDictionary *attributes = self.currentAttributes;
|
||||
NSString *url = attributes[kURLKey];
|
||||
if (!url || url.length < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
RSParsedEnclosure *enclosure = [[RSParsedEnclosure alloc] init];
|
||||
enclosure.url = url;
|
||||
|
||||
NSString *lengthString = attributes[kLengthKey];
|
||||
if (lengthString) {
|
||||
enclosure.length = lengthString.integerValue;
|
||||
}
|
||||
|
||||
enclosure.mimeType = attributes[kTypeKey];
|
||||
|
||||
// The RSS spec specifies zero or one enclosures.
|
||||
// However, the Media RSS namespace allows for more than one.
|
||||
// We could add support for multiple enclosures at some time in the future.
|
||||
self.currentArticle.enclosures = [NSSet setWithObject:enclosure];
|
||||
}
|
||||
|
||||
- (NSString *)urlString:(NSString *)s {
|
||||
|
||||
@ -304,6 +329,9 @@ static const NSInteger kUppercaseRDFLength = 4;
|
||||
else if (RSSAXEqualTags(localName, kTitle, kTitleLength)) {
|
||||
self.currentArticle.title = [self currentStringWithHTMLEntitiesDecoded];
|
||||
}
|
||||
else if (RSSAXEqualTags(localName, kEnclosure, kEnclosureLength)) {
|
||||
[self addEnclosure];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -327,7 +355,7 @@ static const NSInteger kUppercaseRDFLength = 4;
|
||||
}
|
||||
|
||||
NSDictionary *xmlAttributes = nil;
|
||||
if ((self.isRDF && RSSAXEqualTags(localName, kItem, kItemLength)) || RSSAXEqualTags(localName, kGuid, kGuidLength)) {
|
||||
if ((self.isRDF && RSSAXEqualTags(localName, kItem, kItemLength)) || RSSAXEqualTags(localName, kGuid, kGuidLength) || RSSAXEqualTags(localName, kEnclosure, kEnclosureLength)) {
|
||||
xmlAttributes = [self.parser attributesDictionary:attributes numberOfAttributes:numberOfAttributes];
|
||||
}
|
||||
if (self.currentAttributes != xmlAttributes) {
|
||||
|
@ -37,6 +37,7 @@
|
||||
#import <RSParser/RSAtomParser.h>
|
||||
#import <RSParser/RSParsedFeed.h>
|
||||
#import <RSParser/RSParsedArticle.h>
|
||||
#import <RSParser/RSParsedEnclosure.h>
|
||||
|
||||
// HTML
|
||||
|
||||
|
@ -7,6 +7,9 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
8401FF811FE862E70080F13F /* RSParsedEnclosure.h in Headers */ = {isa = PBXBuildFile; fileRef = 8401FF7F1FE862E70080F13F /* RSParsedEnclosure.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8401FF821FE862E70080F13F /* RSParsedEnclosure.m in Sources */ = {isa = PBXBuildFile; fileRef = 8401FF801FE862E70080F13F /* RSParsedEnclosure.m */; };
|
||||
8401FF841FE87C2F0080F13F /* theomnishow.rss in Resources */ = {isa = PBXBuildFile; fileRef = 8401FF831FE87C2E0080F13F /* theomnishow.rss */; };
|
||||
840FDCB21F01FED00041F61B /* RSSParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840FDCB11F01FED00041F61B /* RSSParserTests.swift */; };
|
||||
840FDCB41F0217410041F61B /* JSONFeedParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840FDCB31F0217410041F61B /* JSONFeedParserTests.swift */; };
|
||||
840FDCB61F0217D20041F61B /* AtomParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 840FDCB51F0217D20041F61B /* AtomParserTests.swift */; };
|
||||
@ -111,6 +114,9 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
8401FF7F1FE862E70080F13F /* RSParsedEnclosure.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RSParsedEnclosure.h; sourceTree = "<group>"; };
|
||||
8401FF801FE862E70080F13F /* RSParsedEnclosure.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RSParsedEnclosure.m; sourceTree = "<group>"; };
|
||||
8401FF831FE87C2E0080F13F /* theomnishow.rss */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = theomnishow.rss; sourceTree = "<group>"; };
|
||||
840FDCB11F01FED00041F61B /* RSSParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSSParserTests.swift; sourceTree = "<group>"; };
|
||||
840FDCB31F0217410041F61B /* JSONFeedParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSONFeedParserTests.swift; sourceTree = "<group>"; };
|
||||
840FDCB51F0217D20041F61B /* AtomParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AtomParserTests.swift; sourceTree = "<group>"; };
|
||||
@ -343,6 +349,8 @@
|
||||
84469D221EFA3134004A6B28 /* RSParsedArticle.m */,
|
||||
84469D231EFA3134004A6B28 /* RSParsedFeed.h */,
|
||||
84469D241EFA3134004A6B28 /* RSParsedFeed.m */,
|
||||
8401FF7F1FE862E70080F13F /* RSParsedEnclosure.h */,
|
||||
8401FF801FE862E70080F13F /* RSParsedEnclosure.m */,
|
||||
);
|
||||
name = XML;
|
||||
path = Feeds/XML;
|
||||
@ -381,6 +389,7 @@
|
||||
84628AAC1FCA10AE00566A9B /* allthis.atom */,
|
||||
84566D931FD0ABFB00103322 /* allthis.json */,
|
||||
84566D951FD1FC1800103322 /* allthis-partial.json */,
|
||||
8401FF831FE87C2E0080F13F /* theomnishow.rss */,
|
||||
849A03CF1F0081EA00122600 /* Subs.opml */,
|
||||
);
|
||||
path = Resources;
|
||||
@ -454,6 +463,7 @@
|
||||
84469CFC1EFA3069004A6B28 /* RSSAXParser.h in Headers */,
|
||||
845213281FCB4042003B6E93 /* RSHTMLTag.h in Headers */,
|
||||
84E7E69F1F85780D0046719D /* ParserData.h in Headers */,
|
||||
8401FF811FE862E70080F13F /* RSParsedEnclosure.h in Headers */,
|
||||
84469D071EFA307E004A6B28 /* RSHTMLLinkParser.h in Headers */,
|
||||
84469D0D1EFA307E004A6B28 /* RSSAXHTMLParser.h in Headers */,
|
||||
84469D2B1EFA3134004A6B28 /* RSParsedArticle.h in Headers */,
|
||||
@ -561,6 +571,7 @@
|
||||
840FDCBA1F02186D0041F61B /* DaringFireball.json in Resources */,
|
||||
849A03D21F0081EA00122600 /* EMarley.rss in Resources */,
|
||||
849A03DA1F0081EA00122600 /* Subs.opml in Resources */,
|
||||
8401FF841FE87C2F0080F13F /* theomnishow.rss in Resources */,
|
||||
849A03D61F0081EA00122600 /* manton.rss in Resources */,
|
||||
849A03D11F0081EA00122600 /* DaringFireball.rss in Resources */,
|
||||
84B19A771FDA438300458981 /* natasha.xml in Resources */,
|
||||
@ -613,6 +624,7 @@
|
||||
84285AAA1F006456002E8708 /* RSParsedFeedTransformer.swift in Sources */,
|
||||
84469D2E1EFA3134004A6B28 /* RSParsedFeed.m in Sources */,
|
||||
84469CF81EFA3000004A6B28 /* RSOPMLParser.m in Sources */,
|
||||
8401FF821FE862E70080F13F /* RSParsedEnclosure.m in Sources */,
|
||||
84469D401EFF29A9004A6B28 /* FeedParserError.swift in Sources */,
|
||||
84469D321EFA31CF004A6B28 /* FeedParser.swift in Sources */,
|
||||
84469D281EFA3134004A6B28 /* RSAtomParser.m in Sources */,
|
||||
|
@ -54,4 +54,20 @@ class RSSParserTests: XCTestCase {
|
||||
XCTAssertEqual(parsedFeed.items.count, 10)
|
||||
}
|
||||
|
||||
func testTheOmniShowAttachments() {
|
||||
|
||||
let d = parserData("theomnishow", "rss", "https://theomnishow.omnigroup.com/")
|
||||
let parsedFeed = try! FeedParser.parse(d)!
|
||||
|
||||
for article in parsedFeed.items {
|
||||
XCTAssertNotNil(article.attachments)
|
||||
XCTAssertEqual(article.attachments!.count, 1)
|
||||
let attachment = Array(article.attachments!).first!
|
||||
XCTAssertNotNil(attachment.mimeType)
|
||||
XCTAssertNotNil(attachment.sizeInBytes)
|
||||
XCTAssert(attachment.url.contains("cloudfront"))
|
||||
XCTAssertGreaterThanOrEqual(attachment.sizeInBytes!, 22275279)
|
||||
XCTAssertEqual(attachment.mimeType, "audio/mpeg")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
135
Frameworks/RSParser/RSParserTests/Resources/theomnishow.rss
Normal file
135
Frameworks/RSParser/RSParserTests/Resources/theomnishow.rss
Normal file
@ -0,0 +1,135 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"><channel><title>The Omni Show</title><link>https://theomnishow.omnigroup.com/</link><atom:link href="https://theomnishow.omnigroup.com/rss/" rel="self" type="application/rss+xml" /><language>en-us</language><copyright>℗ & © 2017 The Omni Group</copyright><itunes:subtitle>Get to know the people and stories behind Omni’s award-winning productivity apps for Mac and iOS.</itunes:subtitle><itunes:author>The Omni Group</itunes:author><itunes:summary>Get to know the people and stories behind Omni’s award-winning productivity apps for Mac and iOS.</itunes:summary><description>Get to know the people and stories behind Omni’s award-winning productivity apps for Mac and iOS.</description><itunes:owner><itunes:name>The Omni Group</itunes:name><itunes:email>theomnishow@omnigroup.com</itunes:email></itunes:owner><itunes:image href="https://theomnishow.omnigroup.com/assets/img/omnishow-cover-1x3000.jpg" /><itunes:category text="Technology"><itunes:category text="Tech News" /></itunes:category><itunes:explicit>no</itunes:explicit><item><title>Andrea McVittie, User Experience Designer</title><itunes:author>The Omni Group</itunes:author><link>https://theomnishow.omnigroup.com/episode/andrea-mcvittie-user-experience-designer/</link><description>Andrea studied fine art at <a href="https://msu.edu/">Michigan State</a> and human-computer interaction at the <a href="https://www.umich.edu/">University of Michigan</a>. One day, while working at the school library, it was discovered that she could make websites — which launched her career as a UX designer, and since 2012 she’s been designing apps at Omni.</description><itunes:image href="https://theomnishow.omnigroup.com/assets/img/omnishow-cover-1x3000.jpg" /><enclosure length="24388318" type="audio/mpeg" url="https://d2vstsfo8knv0p.cloudfront.net/audio/the-omni-show-004.mp3" /><guid>https://theomnishow.omnigroup.com/episode/andrea-mcvittie-user-experience-designer/</guid><pubDate>Wed, 06 Dec 2017 14:00:00 +0000</pubDate><itunes:duration>28:49</itunes:duration><content:encoded>Full transcript and show notes at <a href='https://theomnishow.omnigroup.com/episode/andrea-mcvittie-user-experience-designer/'>theomnishow.omnigroup.com</a>
|
||||
|
||||
<p>Andrea studied fine art at <a href="https://msu.edu/">Michigan State</a> and human-computer interaction at the <a href="https://www.umich.edu/">University of Michigan</a>. One day, while working at the school library, it was discovered that she could make websites — which launched her career as a UX designer, and since 2012 she’s been designing apps at Omni.</p>
|
||||
|
||||
<p>Andrea, it must be told, is firmly against stealing money from puppies — or maybe she’s against treating puppies as a particularly cuddly form of currency and then stealing <em>them</em>.</p>
|
||||
<p>Nobody knows which. Don’t do either!</p>
|
||||
<p>You can find Andrea <a href="https://twitter.com/amcvittie">@amcvittie</a> on Twitter. And you can find her work in every single Omni app.</p>
|
||||
<p>Some other people, places, and things mentioned:</p>
|
||||
<ul>
|
||||
<li><a href="https://www.nngroup.com/articles/definition-user-experience/">User Experience (UX)</a></li>
|
||||
<li><a href="https://usabilitygeek.com/ethics-in-user-experience-design/">User Experience and Ethics</a></li>
|
||||
<li><a href="https://twitter.com/monteiro">Mike Monteiro</a></li>
|
||||
<li><a href="https://www.omnigroup.com/blog/omnifocus-now-supports-end-to-end-encryption">OmniFocus Sync Encryption</a></li>
|
||||
<li><a href="https://twitter.com/timothyekl">Tim Ekl</a></li>
|
||||
<li><a href="https://www.omnigroup.com/omnigraffle">OmniGraffle</a></li>
|
||||
<li><a href="https://www.apple.com/apple-pencil/">Apple Pencil</a></li>
|
||||
<li><a href="https://www.omnigroup.com/blog/omni-roadmap-2017-q4-update">OmniFocus Tags</a></li>
|
||||
<li><a href="http://vesperapp.co/">Vesper</a></li>
|
||||
<li><a href="https://theomnishow.omnigroup.com/episode/curt-clifton-omnifocus-engineer">Curt Clifton</a></li>
|
||||
<li><a href="https://twitter.com/jimcorreia">Jim Correia</a></li>
|
||||
<li><a href="https://darkpatterns.org/">darkpatterns.org</a></li>
|
||||
<li><a href="http://www.seattleartmuseum.org/">Seattle Art Museum</a></li>
|
||||
<li><a href="https://twitter.com/OmniGroup/status/921132286527004672">Omni Slack Group</a></li>
|
||||
<li><a href="http://www.rosemaryorchard.com/en">Rosemary Orchard</a></li>
|
||||
<li><a href="https://support.omnigroup.com/">Omni Support</a></li>
|
||||
<li><a href="https://twitter.com/KelStewart84/status/928377769561546752">Listener question from Twitter</a></li>
|
||||
<li><a href="https://lib.msu.edu/">Michigan State Library</a></li>
|
||||
<li><a href="https://twitter.com/Photoshop">Adobe Photoshop</a></li>
|
||||
<li><a href="http://annarborchronicle.com/2012/05/03/in-the-archives-poison-pages/">Shadows from the Walls of Death</a></li>
|
||||
<li><a href="https://www.si.umich.edu/">University of Michigan School of Information</a></li>
|
||||
<li><a href="https://www.instagram.com/p/Baztg5FF7wJ/">Oliver, who’s a good dog</a></li>
|
||||
</ul></content:encoded><itunes:explicit>no</itunes:explicit></item><item><title>Brian Covey, Support Manager</title><itunes:author>The Omni Group</itunes:author><link>https://theomnishow.omnigroup.com/episode/brian-covey-support-manager/</link><description>Brian Covey studied computer science at <a href="http://www.evergreen.edu/">The Evergreen State College</a> — which your host also attended, but back before computers were a thing. After some normal young-person-bouncing-around a little, Brian came to shore at Omni in 2001, where he became the leader, dear and fearless, of Omni’s Support Humans.</description><itunes:image href="https://theomnishow.omnigroup.com/assets/img/omnishow-cover-1x3000.jpg" /><enclosure length="24985882" type="audio/mpeg" url="https://d2vstsfo8knv0p.cloudfront.net/audio/the-omni-show-003.mp3" /><guid>https://theomnishow.omnigroup.com/episode/brian-covey-support-manager/</guid><pubDate>Wed, 22 Nov 2017 14:00:00 +0000</pubDate><itunes:duration>29:32</itunes:duration><content:encoded>Full transcript and show notes at <a href='https://theomnishow.omnigroup.com/episode/brian-covey-support-manager/'>theomnishow.omnigroup.com</a>
|
||||
|
||||
<p>Brian Covey studied computer science at <a href="http://www.evergreen.edu/">The Evergreen State College</a> — which your host also attended, but back before computers were a thing. After some normal young-person-bouncing-around a little, Brian came to shore at Omni in 2001, where he became the leader, dear and fearless, of Omni’s Support Humans.</p>
|
||||
|
||||
<p>You can find Brian <a href="https://twitter.com/hidvorak">@hidvorak</a> on Twitter. (You can contact Omni support at <a href="https://support.omnigroup.com/">support.omnigroup.com</a>.)</p>
|
||||
<p>You can also find a <a href="https://www.omnigroup.com/blog/Yes_-_The_Omni_Video">video of Brian doing the worm</a> in an Omni commercial from 2006. Absolutely not to be missed!</p>
|
||||
<p>Some other people, places, and things mentioned:</p>
|
||||
<ul>
|
||||
<li><a href="https://cherof.bandcamp.com/">The Music of Aaron Cherof</a> (Aaron works at Omni and does the music for this show)</li>
|
||||
<li><a href="http://elevatesummit.co/">Elevate Support conference</a></li>
|
||||
<li><a href="https://twitter.com/kcase">Ken Case</a></li>
|
||||
<li><a href="https://twitter.com/chuckdude">Chuck Toporek</a></li>
|
||||
<li><a href="https://www.omnigroup.com/more">OmniWeb</a></li>
|
||||
<li><a href="https://www2.gov.bc.ca/">British Columbia</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Ninja">Ninjas</a></li>
|
||||
<li><a href="http://starwars.wikia.com/wiki/Droid">Droids</a></li>
|
||||
<li><a href="https://twitter.com/curtclifton">Curt Clifton</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Pair_programming">Pair programming</a></li>
|
||||
<li><a href="https://www.omnigroup.com/omniplan">OmniPlan</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Babylon_5">Babylon 5</a></li>
|
||||
<li><a href="https://www.seattle.gov/visiting-seattle">Seattle</a></li>
|
||||
<li><a href="http://www.netzero.net/">NetZero</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/MacOS">Mac OS X</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Boomerang">Boomerangs</a></li>
|
||||
<li><a href="http://www.nirvana.com/">Nirvana</a></li>
|
||||
<li><a href="https://www.youtube.com/watch?v=o_hngjZUnOw">K Dorm</a></li>
|
||||
<li><a href="https://www.mopop.org/">Experience Music Project</a> (now MoPOP)</li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Dave_Grohl">Dave Grohl</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Nomeansno">Nomeansno</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Operant_conditioning_chamber">Skinner Box</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/The_Mythical_Man-Month">Mythical Man Month</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Spokane,_Washington">Spokane</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Anton%C3%ADn_Dvořák">Antonín Dvořák</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard">Dvorak keyboard</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Repetitive_strain_injury">Repetitive Strain Injury (RSI)</a></li>
|
||||
</ul></content:encoded><itunes:explicit>no</itunes:explicit></item><item><title>Curt Clifton, OmniFocus Engineer</title><itunes:author>The Omni Group</itunes:author><link>https://theomnishow.omnigroup.com/episode/curt-clifton-omnifocus-engineer/</link><description>Curt Clifton came to Omni while on sabbatical from his computer science professorship at <a href="http://www.rose-hulman.edu/">Rose-Hulman</a> — and never went back. He’s spent much of his six years at Omni on the <a href="https://www.omnigroup.com/omnifocus">OmniFocus</a> team, where he clicks checkboxes for a living.</description><itunes:image href="https://theomnishow.omnigroup.com/assets/img/omnishow-cover-1x3000.jpg" /><enclosure length="24354550" type="audio/mpeg" url="https://d2vstsfo8knv0p.cloudfront.net/audio/the-omni-show-002.mp3" /><guid>https://theomnishow.omnigroup.com/episode/curt-clifton-omnifocus-engineer/</guid><pubDate>Mon, 06 Nov 2017 17:00:00 +0000</pubDate><itunes:duration>28:47</itunes:duration><content:encoded>Full transcript and show notes at <a href='https://theomnishow.omnigroup.com/episode/curt-clifton-omnifocus-engineer/'>theomnishow.omnigroup.com</a>
|
||||
|
||||
<p>Curt Clifton came to Omni while on sabbatical from his computer science professorship at <a href="http://www.rose-hulman.edu/">Rose-Hulman</a> — and never went back. He’s spent much of his six years at Omni on the <a href="https://www.omnigroup.com/omnifocus">OmniFocus</a> team, where he clicks checkboxes for a living.</p>
|
||||
|
||||
<p>Curt’s a fan of the local <a href="https://www.soundersfc.com/">association football team</a>. He also likes woodworking and distance-running, though he has yet to explore the synergistic possibilities of doing both at the same time.</p>
|
||||
<p>You can find Curt <a href="https://twitter.com/curtclifton">@curtclifton</a> on Twitter and at <a href="http://curtclifton.net/">curtclifton.net</a>.</p>
|
||||
<p>Some other people, places, and things mentioned:</p>
|
||||
<ul>
|
||||
<li><a href="https://developer.apple.com/ios/drag-and-drop/">iOS 11 drag and drop</a></li>
|
||||
<li><a href="https://www.omnigroup.com/blog/omni-roadmap-2017-q4-update">OmniFocus 3: tags</a></li>
|
||||
<li><a href="https://support.apple.com/en-us/HT206481">Files app</a></li>
|
||||
<li><a href="https://developer.apple.com/wwdc/">World Wide Developer’s Conference (WWDC) (aka Dub Dub)</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Lake_Union">Lake Union</a></li>
|
||||
<li><a href="https://arstechnica.com/gadgets/2013/09/ios-7-thoroughly-reviewed/">iOS 7</a></li>
|
||||
<li><a href="https://www.apple.com/iphone-x/">The notch</a></li>
|
||||
<li><a href="https://macosxautomation.com/applescript/">AppleScript</a></li>
|
||||
<li><a href="https://www.omnigroup.com/omnioutliner">OmniOutliner</a></li>
|
||||
<li><a href="http://ethanschoonover.com/">Ethan Schoonover</a></li>
|
||||
<li><a href="http://shawnblanc.net/2014/03/history-of-omnifocus-for-mac/">Kinkless GTD</a></li>
|
||||
<li><a href="http://gettingthingsdone.com/">Getting Things Done, by David Allen</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Indiana">Indiana</a></li>
|
||||
<li><a href="https://discourse.omnigroup.com/">Omni Forums</a></li>
|
||||
<li><a href="https://twitter.com/kcase">Ken Case</a></li>
|
||||
<li><a href="https://twitter.com/tjw">Tim Wood</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Amish">The Amish</a></li>
|
||||
<li><a href="https://twitter.com/vanillaice">Vanilla Ice</a></li>
|
||||
<li><a href="http://www.imdb.com/title/tt0090555/">Crocodile Dundee</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Pennsylvania_Dutch_Country">Pennsylvania Dutch Country</a></li>
|
||||
<li><a href="http://www.goodnplenty.com">Good ’N Plenty Restaurant</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Amana_Colonies">Amana Colonies</a></li>
|
||||
<li><a href="https://twitter.com/timothyekl">Tim Ekl</a></li>
|
||||
<li><a href="https://twitter.com/jimcorreia">Jim Correia</a></li>
|
||||
<li><a href="https://www.pomona.edu/">Pomona College</a></li>
|
||||
<li><a href="https://www.hmc.edu/">Harvey Mudd College</a></li>
|
||||
<li><a href="https://twitter.com/reid_callan">Reid Callan</a></li>
|
||||
<li><a href="https://twitter.com/tbunch">Tom Bunch</a></li>
|
||||
<li><a href="https://www.mlb.com/cubs">Cubs</a></li>
|
||||
<li><a href="https://www.mlssoccer.com/">Major League Soccer Cup</a></li>
|
||||
<li><a href="http://www.baa.org/races/boston-marathon.aspx">Boston Marathon</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Battle_of_Marathon">Marathon</a></li>
|
||||
<li><a href="https://support.omnigroup.com/">Support Humans</a></li>
|
||||
</ul></content:encoded><itunes:explicit>no</itunes:explicit></item><item><title>Kristina Sontag, Software Test Manager</title><itunes:author>The Omni Group</itunes:author><link>https://theomnishow.omnigroup.com/episode/kristina-sontag-software-test-manager/</link><description>For our first episode we interview Kristina Sontag, who runs Omni’s test department — a group tireless, fearless, and strikingly effective in its hunt for bugs.</description><itunes:image href="https://theomnishow.omnigroup.com/assets/img/omnishow-cover-1x3000.jpg" /><enclosure length="22275279" type="audio/mpeg" url="https://d2vstsfo8knv0p.cloudfront.net/audio/the-omni-show-001.mp3" /><guid>https://theomnishow.omnigroup.com/episode/kristina-sontag-software-test-manager/</guid><pubDate>Wed, 01 Nov 2017 16:00:00 +0000</pubDate><itunes:duration>26:18</itunes:duration><content:encoded>Full transcript and show notes at <a href='https://theomnishow.omnigroup.com/episode/kristina-sontag-software-test-manager/'>theomnishow.omnigroup.com</a>
|
||||
|
||||
<p>For our first episode we interview Kristina Sontag, who runs Omni’s test department — a group tireless, fearless, and strikingly effective in its hunt for bugs.</p>
|
||||
|
||||
<p>Kristina got her start playing games for a living at <a href="http://lucasfilm.com/games">LucasArts</a>. Between there and today she’s also worked on <a href="https://web.archive.org/web/19970105135152/http://www.edmark.com/">educational software</a>, gotten a pilot’s license, volunteered for <a href="http://appcamp4girls.com/">App Camp for Girls</a>, and helped organize the <a href="https://www.weareecs.com/">Emerald City Supporters</a>.</p>
|
||||
<p>When she’s not doing everything else, she’s playing <a href="https://www.destinythegame.com/">Destiny</a>. She may even be thinking about Destiny at this very moment.</p>
|
||||
<p>You can find Kristina on Twitter <a href="https://twitter.com/knsontag">@knsontag</a>.</p>
|
||||
<p>Some other people and places mentioned:</p>
|
||||
<ul>
|
||||
<li><a href="https://developer.apple.com/wwdc/">WWDC</a></li>
|
||||
<li><a href="https://twitter.com/macgenie">Jean McDonald</a></li>
|
||||
<li><a href="https://twitter.com/emarley">Liz Marley</a></li>
|
||||
<li><a href="https://twitter.com/uipoptart">Grey Osten</a></li>
|
||||
<li><a href="https://itunes.apple.com/us/developer/app-camp-for-girls/id942207153">App Camp App</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Santa_Rosa,_California">Santa Rosa, CA</a></li>
|
||||
<li><a href="http://www.ilm.com/">Industrial Light &amp; Magic (ILM)</a></li>
|
||||
<li><a href="http://lucasfilm.com/skywalker-ranch-marin">Skywalker Ranch</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/George_Lucas">George Lucas</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Ron_Gilbert">Ron Gilbert</a></li>
|
||||
<li><a href="http://humongous.com/">Humongous Entertainment</a></li>
|
||||
<li><a href="https://www.omnigroup.com/omnifocus">OmniFocus for iPhone</a></li>
|
||||
<li><a href="https://twitter.com/hidvorak">Brian Covey</a></li>
|
||||
<li><a href="https://twitter.com/kcase">Ken Case</a></li>
|
||||
<li><a href="https://en.wikipedia.org/wiki/Floatplane">Float plane</a></li>
|
||||
<li><a href="https://www.kenmoreair.com/">Kenmore Air</a></li>
|
||||
<li><a href="https://www.soundersfc.com/">Seattle Sounders</a></li>
|
||||
<li><a href="https://www.mlssoccer.com/">Major League Soccer (MLS)</a></li>
|
||||
</ul></content:encoded><itunes:explicit>no</itunes:explicit></item></channel></rss>
|
Loading…
x
Reference in New Issue
Block a user